home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / nrd33.zip / NRD.PAS < prev    next >
Pascal/Delphi Source File  |  1991-05-19  |  93KB  |  3,086 lines

  1. {$I-}
  2. {$V-}
  3. {$M 60000,0,655360}
  4.  
  5. {  ROUTINE:    N R D
  6.  
  7.    PURPOSE:    Control an NRD525 / NRD535 Receiver + database
  8.  
  9.    USAGE:    nrd
  10.  
  11.    AUTHOR:    Tom Whiteside 11505 Oak View, Austin, TX 78759 (512) 258-5924
  12.  
  13.    REVISION:    1.0  04-30-90  TGW  Initial Release
  14.                 1.1  07-07-90  TGW  Serial routines changed to use BIOS for
  15.                                        Windows
  16.                 1.2  07-15-90  TGW  Efficiency tweaks to inc/dec bw/mode
  17.                                     Cursor Highlighting for current line
  18.                                     Cursor tracking data for inc/dec freq
  19.                 1.3  07-29-90  TGW  Remove H(ide from prompt, fix Delete
  20.                                        leaving wrong line highlighted
  21.                                     Added Revision to prompt
  22.                 1.4  09-03-90  TGW  Fixed inc/dec mode past boundary crashing
  23.                                        program; asserted black backgrd on
  24.                                        title and journal
  25.                 1.5  09-29-90  TGW  Added MAP feature
  26.  
  27.                 1.6  11-18-90  TGW  Fixed 2 bugs where cursor got out of
  28.                                     sync with "status line"
  29.                 2.0  12/01-90  TGW  Mods to support other com ports, optional
  30.                                     MAP, help                                 easier for o
  31.                 2.1  12-02-90  TGW  Added time offset to config.dat; fixed
  32.                                     home not putting cursor at top of screen
  33.  
  34.                 2.2  12-25-90  TGW  Added "Com 0" feature to allow using prgm
  35.                                     without serial port...
  36.                 2.3  12-27-90  TGW  Fix to eliminate hang if radio off
  37.  
  38.                 2.4  03-02-91  TGW  Fix for monochrome users (in screen.pas)
  39.                 2.5  03-10-91  TGW  Added Import of Sundstrom data
  40.                 2.6  03-30-91  TGW  Added Active and Inactive log concept
  41.                                     including write from the inactive log
  42.                                     Added "*" command to find radio freq
  43.                                     in database.  Fixed potential hang in
  44.                                     comreadln.  Reduced edit field length
  45.                                     for comments by 1 char.  (Fixed wrap bug
  46.                                     for bottom line)  Removed dangerous Read
  47.                                     command from Journal
  48.                 2.7  04-14-91  TGW  Fixed display bug in inc_freq
  49.                 3.0  04-26-91  TGW  Added NRD535 features
  50.                 3.1  04-27-91  TGW  Fix to journal name select; Added 535
  51.                                     mode to auto-update receiver display
  52.                 3.2  05-12-91  TGW  Added S-meter to 535; changed mode order
  53.                                     to AM -> ECSS_U; added graphics command
  54.                                     for 535; misc bug fixes for 535
  55.  
  56.                 3.2  05-19-91  TGW  Graphics enhancements; commands for time
  57.                                     and spectral displays.  Performance
  58.                                     enhancement to Spectral display
  59. }
  60. program nrd(input,output);
  61.  
  62. uses async, crt, dos, graph, screen, nrdio, nrdutil;
  63.  
  64. const LINES       = 25;
  65.       CHARPERLINE = 80;
  66.       BACKTAB     = chr(10);
  67.       TAB         = chr(9);
  68.       PAGEUP      = chr(3);
  69.       PAGEDOWN    = chr(4);
  70.       UP          = chr(15);
  71.       DOWN        = chr(11);
  72.       RIGHTARROW  = chr(21);
  73.       LEFTARROW   = chr(7);
  74.       CTRLPAGEUP  = chr(14);
  75.       CTRLPAGEDN  = chr(16);
  76.       HOMEKY      = chr(5);
  77.       ENDKY       = chr(6);
  78.       REMOTE_DLY  = 300; { msec }
  79.       MAP_OFFSET  = 2.0; { frequency offset from center for sync det. }
  80.  
  81. var i,cnt: integer;
  82.     ch:char;
  83.     s:string;
  84.     oldstat:receivertype;
  85.     logbuf:file;
  86.     logentry:logtype;
  87.     min_mark,max_mark:word;
  88.     rslt:integer;
  89.     display_page:integer;
  90.     update_receiver_display:boolean;
  91.     displayed_freq:array[1..LINES] of real;
  92.     displayed_lines:integer;
  93.     map:boolean;
  94.     last_log:integer;  { used for hot keying between active and last log }
  95.     last_log_data:logtype; { used to copy data from last log to active log }
  96.     old_time_stamp, time_stamp:word;
  97.     enable_s_meter:boolean;
  98.     meter_reading:integer;
  99.     graphmode:integer;
  100.  
  101.   procedure status_window;
  102.   begin
  103.     window(1,25,80,25);
  104.     gotoxy(1,1);
  105.     writea(BLACK,BACKGROUND);
  106.     writea(LIGHTGRAY, FOREGROUND);
  107.     write(output,'Active Log: ');
  108.     writea(CYAN, FOREGROUND);
  109.     write(output,loglist.log[loglist.currentlog].logname);
  110.     if last_log <> 0 then
  111.       begin
  112.         writea(LIGHTGRAY, FOREGROUND);
  113.         write(output,'  Inactive Log: ');
  114.         writea(CYAN, FOREGROUND);
  115.         write(output,loglist.log[last_log].logname);
  116.       end;
  117.   end;
  118.  
  119.   procedure clear_log(var logdata:logtype);
  120.   const GMTCONST = 6; { bug: must manually update with time change }
  121.  
  122.   var dy,yr,mo,dyofweek,hour,minute,sec,sec100:word;
  123.       t:string;
  124.   begin
  125.     getdate(yr,mo,dy,dyofweek);
  126.     gettime(hour,minute,sec,sec100);
  127.     hour:=hour + gmt_offset;
  128.     if hour >= 24 then
  129.       begin
  130.         hour:=hour - 24;
  131.         dy:=dy + 1;
  132.         if dy > 31 then { kludge date, doesn't allow for 30 day mo, etc }
  133.           begin
  134.             dy:=1;
  135.             mo:=mo + 1;
  136.             if mo > 12 then mo:=1;
  137.           end;
  138.       end;
  139.     with logdata do
  140.       begin
  141.         {init date to today's date in yymmdd format }
  142.         str(yr,t); delete(t,1,2);
  143.         date:=t;
  144.         str(mo,t);
  145.         if length(t) < 2 then t:=concat('0',t);
  146.         date:=concat(date,t);
  147.         str(dy,t);
  148.         if length(t) < 2 then t:=concat('0',t);
  149.         date:=concat(date,t);
  150.  
  151.         { init time in gmt }
  152.  
  153.         str(hour,t);
  154.         while length(t) < 2 do t:=concat('0',t);
  155.         begin_time:=t;
  156.         str(minute,t);
  157.         while length(t) < 2 do t:=concat('0',t);
  158.         begin_time:=concat(begin_time,t);
  159.         end_time:=begin_time;
  160.         frequency:= receiverstat.frequency;
  161.         callsign:=  '';
  162.         location:=  '';
  163.         comment:=   '';
  164.         mode:=      receiverstat.mode;
  165.         bandwidth:= receiverstat.bandwidth;
  166.         agc:=       receiverstat.agc;
  167.         attenuator:=receiverstat.attenuator;
  168.       end;
  169.   end;
  170.  
  171.   procedure draw_display_titles;
  172.   begin
  173.     top_window;
  174.     gotoxy(1,5);
  175.     clreol;
  176.     case display_page of
  177.       1: begin
  178.            gotoxy(2,5);
  179.            write(output,'Num');
  180.            gotoxy(7,5);
  181.            write(output,'Date');
  182.            gotoxy(13,5);
  183.            write(output,'Strt');
  184.            gotoxy(18,5);
  185.            write(output,'End');
  186.            gotoxy(24,5);
  187.            write(output,'Freq');
  188.            gotoxy(32,5);
  189.            write(output,'Station ID');
  190.            gotoxy(52,5);
  191.            write(output,'Location');
  192.          end;
  193.       2: begin
  194.            gotoxy(3,5);
  195.            write(output,'Freq');
  196.            gotoxy(11,5);
  197.            write(output,'Comment');
  198.          end;
  199.       3: begin
  200.            gotoxy(2,5);
  201.            write(output,'Num');
  202.            gotoxy(7,5);
  203.            write(output,'Date');
  204.            gotoxy(13,5);
  205.            write(output,'Strt');
  206.            gotoxy(18,5);
  207.            write(output,'End');
  208.            gotoxy(24,5);
  209.            write(output,'Freq');
  210.            gotoxy(32,5);
  211.            write(output,'Mode');
  212.            gotoxy(39,5);
  213.            write(output,'BW');
  214.            gotoxy(43,5);
  215.            write(output,'AGC');
  216.            gotoxy(48,5);
  217.            write(output,'Attn');
  218.          end;
  219.     end;
  220.   end;
  221.  
  222.   procedure init_rec_window;
  223.  
  224.     procedure draw_box(width,hieght:integer);
  225.     const TL = chr(201);
  226.           TR = chr(187);
  227.           BL = chr(200);
  228.           BR = chr(188);
  229.           HZ = chr(205);
  230.           VT = chr(186);
  231.  
  232.     var i:integer;
  233.  
  234.       procedure draw_horiz;
  235.       var i:integer;
  236.       begin
  237.         for i:=1 to width - 2 do write(output,HZ);
  238.       end;
  239.  
  240.     begin
  241.       { draw top }
  242.       gotoxy(1,2);
  243.       write(output,TL);
  244.       draw_horiz;
  245.       write(output,TR);
  246.  
  247.       { draw sides }
  248.       for i:=1 to hieght - 2 do
  249.         begin
  250.           gotoxy(1,i + 2);      write(output,VT);
  251.           gotoxy(width, i + 2); write(output,VT);
  252.         end;
  253.  
  254.       { draw bottom }
  255.       gotoxy(1,hieght + 1);
  256.       write(output,BL);
  257.       draw_horiz;
  258.       write(output,BR);
  259.     end;
  260.  
  261.   begin
  262.     top_window;
  263.     writea(BLACK,BACKGROUND);
  264.     home;
  265.     cmd_prompt(prompt_num);
  266.     writea(BROWN,FOREGROUND);
  267.     draw_box(REC_WIN_X_BOTTOM - REC_WIN_X_TOP + 1,
  268.              REC_WIN_Y_BOTTOM - REC_WIN_Y_TOP - 1) ;
  269.     gotoxy(30,2);
  270.     writea(LIGHTGRAY,FOREGROUND);
  271.     if radio_type = 525
  272.        then write(output,'NRD 525 Status')
  273.        else write(output,'NRD 535 Status');
  274.     gotoxy(3,3);
  275.     write(output,'Mode:');
  276.     gotoxy(15,3);
  277.     write(output,'BW:');
  278.     gotoxy(29,3);
  279.     write(output,'AGC:');
  280.     if radio_type = 525 then
  281.       begin
  282.         gotoxy(42,3);
  283.         write(output,'Ch:');
  284.       end;
  285.     gotoxy(54,3);
  286.     write(output,'Freq:');
  287.     gotoxy(68,3);
  288.     write(output,' khz');
  289.     display_page:=1;
  290.     writea(LIGHTGRAY,FOREGROUND);
  291.     draw_display_titles;
  292.     writea(LIGHTGRAY,FOREGROUND);
  293.   end;
  294.  
  295.   procedure show_receiver;
  296.   var s:string;
  297.  
  298.     procedure do_out(unchanged:boolean; s:string);
  299.     begin
  300.       if not unchanged then writea(RED,FOREGROUND);
  301.       write(output,s);
  302.       writea(CYAN,FOREGROUND);
  303.     end;
  304.  
  305.   begin
  306.      x_pos:=wherex; y_pos:=wherey;
  307.     top_window;
  308.     writea(CYAN,FOREGROUND);
  309.     with receiverstat do
  310.       begin
  311.         gotoxy(9,3);
  312.         case mode of
  313.           RTTY:     s:='RTTY ';
  314.           CW:       s:='CW   ';
  315.           USB:      s:='USB  ';
  316.           LSB:      s:='LSB  ';
  317.           AM:       s:='AM   ';
  318.           FM:       s:='FM   ';
  319.           FAX:      s:='FAX  ';
  320.           ECSS_USB: s:='ECSSu';
  321.           ECSS_LSB: s:='ECSSl';
  322.         end;
  323.         do_out(receiverstat.mode = oldstat.mode,s);
  324.         gotoxy(19,3);
  325.         case bandwidth of
  326.           WIDE: s:='WIDE ';
  327.           INTER:s:='INTER';
  328.           NARR: s:='NARR ';
  329.           AUX:  s:='AUX  ';
  330.          end;
  331.         do_out(receiverstat.bandwidth = oldstat.bandwidth,s);
  332.          gotoxy(34,3);
  333.          case agc of
  334.            SLOW: s:='SLOW';
  335.            FAST: s:='FAST';
  336.            OFF:  s:='OFF ';
  337.          end;
  338.          do_out(receiverstat.agc = oldstat.agc,s);
  339.          case attenuator of
  340.            YES:  s:='ATT';
  341.            NO:   s:='   ';
  342.          end;
  343.          gotoxy(74,3);
  344.          do_out(receiverstat.attenuator = oldstat.attenuator,s);
  345.          if radio_type = 525 then
  346.            begin
  347.              gotoxy(46,3);
  348.              str(channel:3,s);
  349.              do_out(receiverstat.channel = oldstat.channel,s);
  350.            end;
  351.          gotoxy(60,3);
  352.          str(frequency:8:2,s);
  353.          do_out(receiverstat.frequency = oldstat.frequency,s);
  354.          gotoxy(78,3);
  355.          if map then write(output,'K') else write(output,' ');
  356.          writea(LIGHTGRAY,FOREGROUND);
  357.       end;
  358.     bottom_window;
  359.     oldstat:=receiverstat;
  360.     gotoxy(x_pos,y_pos);
  361.   end;
  362.  
  363.  
  364.   procedure program_radio(log_entry:logtype);
  365.  
  366.   { set receiver to log entry; side effect - zaps channel 199 on 535 }
  367.  
  368.   begin
  369.     remote_on;
  370.     if radio_type = 535 then
  371.         with log_entry do
  372.           set_all(199,attenuator,bandwidth,mode,frequency,agc)
  373.     else
  374.       begin
  375.         if map then {force to AM}
  376.           begin
  377.             set_freq(log_entry.frequency + MAP_OFFSET);
  378.             set_mode(AM);
  379.             set_bandwidth(WIDE);
  380.             set_agc(FAST);
  381.           end
  382.         else {use log entry}
  383.           begin
  384.             set_freq(log_entry.frequency);
  385.             if (radio_type = 525) and (log_entry.mode in [ECSS_USB,ECSS_LSB])
  386.                then log_entry.mode:=AM;
  387.             set_mode(log_entry.mode);
  388.             set_bandwidth(log_entry.bandwidth);
  389.             set_agc(log_entry.agc);
  390.           end;
  391.         set_attenuator(log_entry.attenuator);
  392.       end;
  393.     remote_off(REMOTE_DLY);
  394.     update_receiver_display:=TRUE;
  395.   end;
  396.  
  397.   function mode_to_str(mode:modetype):short_str;
  398.   var s:short_str;
  399.   begin
  400.     case mode of
  401.       RTTY:     s:='RTTY';
  402.       CW:       s:=' CW';
  403.       USB:      s:='USB';
  404.       LSB:      s:='LSB';
  405.       AM:       s:=' AM';
  406.       FM:       s:=' FM';
  407.       FAX:      s:='FAX';
  408.       ECSS_USB: s:='ECSSu';
  409.       ECSS_LSB: s:='ECSSl';
  410.     end;
  411.     mode_to_str:=s;
  412.   end;
  413.  
  414.   function bandwidth_to_str(bandwidth:bandwidthtype):short_str;
  415.   var s:short_str;
  416.   begin
  417.     case bandwidth of
  418.       NARR:  s:=' NARR';
  419.       INTER: s:='INTER';
  420.       WIDE:  s:=' WIDE';
  421.       AUX:   s:=' AUX';
  422.     end;
  423.     bandwidth_to_str:=s;
  424.   end;
  425.  
  426.   procedure show_log_line(logdata:logtype;rec,i:word);
  427.  
  428.     procedure show_line1;
  429.     begin
  430.       write(output,rec:4);
  431.       with logdata do
  432.         begin
  433.           gotoxy(6,i);
  434.           write(output,date);
  435.           gotoxy(13,i);
  436.           write(output,begin_time);
  437.           gotoxy(18,i);
  438.           write(output,end_time);
  439.           gotoxy(23,i);
  440.           write(output,frequency:8:2);
  441.           gotoxy(32,i);
  442.           write(output,callsign);
  443.           gotoxy(52,i);
  444.           write(output,location);
  445.         end;
  446.     end;
  447.  
  448.     procedure show_line2;
  449.     begin
  450.       with logdata do
  451.         begin
  452.           gotoxy(2,i);
  453.           write(output,frequency:8:2);
  454.           gotoxy(11,i);
  455.           write(output,comment);
  456.         end;
  457.     end;
  458.  
  459.     procedure show_line3;
  460.     var s:short_str;
  461.     begin
  462.       write(output,rec:4);
  463.       with logdata do
  464.         begin
  465.           gotoxy(6,i);
  466.           write(output,date);
  467.           gotoxy(13,i);
  468.           write(output,begin_time);
  469.           gotoxy(18,i);
  470.           write(output,end_time);
  471.           gotoxy(23,i);
  472.           write(output,frequency:8:2);
  473.           gotoxy(32,i);
  474.           s:=mode_to_str(mode);
  475.           write(output,s);
  476.           gotoxy(37,i);
  477.           s:=bandwidth_to_str(bandwidth);
  478.           write(output,s);
  479.           gotoxy(43,i);
  480.           case agc of
  481.             FAST: write(output,'FAST');
  482.             SLOW: write(output,'SLOW');
  483.             OFF:  write(output,' OFF');
  484.           end;
  485.           gotoxy(49,i);
  486.           case attenuator of
  487.             YES: write(output,'ON');
  488.             NO:  write(output,'OFF');
  489.           end;
  490.         end;
  491.     end;
  492.  
  493.   begin
  494.     gotoxy(1,i); clreol;
  495.     case display_page of
  496.       1: show_line1;
  497.       2: show_line2;
  498.       3: show_line3;
  499.     end;
  500.   end;
  501.  
  502.   function precess(var rec:integer; cnt:integer):boolean;
  503.   { skip cnt displayed records; return TRUE is not past eof }
  504.   var i:integer;
  505.   begin
  506.     for i:=1 to cnt do
  507.       begin
  508.         rec:=rec + 1;
  509.         while (rec < records)
  510.           and (recdata.recstat[recdata.recptr[rec]] <> SHOW) do
  511.             rec:=rec + 1;
  512.       end;
  513.     if rec > records then rec:=records;
  514.     precess:=recdata.recstat[recdata.recptr[rec]] = SHOW;
  515.   end;
  516.  
  517.   procedure sync_loglist;
  518.   var dummy:boolean;
  519.       i,y_pos:integer;
  520.       recnum:integer;
  521.   begin
  522.     y_pos:=wherey;
  523.     i:=loglist.currentlog;
  524.     loglist.log[i].records:=records;
  525.     recnum:=rec - 1;
  526.     dummy:=precess(recnum,y_pos);
  527.     loglist.log[i].rec:=recnum;
  528.     put_loglist(loglist);
  529.   end;
  530.  
  531.   procedure show_log(rec:integer; refresh_screen,highlight:boolean);
  532.   { refresh_screen = TRUE; paint entire screen with log entries
  533.                    = FALSE then highlight line if indicated }
  534.   var i,j,x_temp,y_temp:integer;
  535.       logdata:logtype;
  536.   begin
  537.     writea(CYAN,FOREGROUND); writea(BLACK,BACKGROUND);
  538.     i:=0; j:=rec - 1;
  539.     y_temp:=wherey; { used to highlight cursor line }
  540.     x_temp:=wherex;
  541.     if refresh_screen then home;
  542.     while (i < LINES - REC_WIN_Y_BOTTOM - 1) and (j < records) do
  543.       begin
  544.         inc(i);
  545.         if precess(j,1) then
  546.           begin
  547.             get_log(logbuf,logdata,recdata.recptr[j]);
  548.             displayed_freq[i]:=logdata.frequency;
  549.             if (j >= min_mark) and (j <= max_mark) then
  550.               begin
  551.                 writea(BLACK,FOREGROUND);
  552.                 writea(YELLOW,BACKGROUND);
  553.                 show_log_line(logdata,j,i);
  554.                 writea(BLACK,BACKGROUND);
  555.                 writea(CYAN,FOREGROUND);
  556.               end
  557.             else if (i = y_temp) and highlight then
  558.               begin
  559.                 writea(BLACK,FOREGROUND);
  560.                 writea(CYAN,BACKGROUND);
  561.                 show_log_line(logdata,j,i);
  562.                 writea(BLACK,BACKGROUND);
  563.                 writea(CYAN,FOREGROUND);
  564.               end
  565.             else if refresh_screen or ((i = y_temp) and not highlight)
  566.               then show_log_line(logdata,j,i);
  567.           end;
  568.       end;
  569.     displayed_lines:=i;
  570.     gotoxy(x_temp,y_temp);
  571.   end;
  572.  
  573.   procedure do_mark;
  574.   var recnum:integer;
  575.       dummy:boolean;
  576.  
  577.   begin
  578.     x_pos:=wherex; y_pos:=wherey;
  579.     recnum:=rec - 1;
  580.     dummy:=precess(recnum,y_pos);
  581.     if recnum < min_mark then min_mark:=recnum;
  582.     if recnum > max_mark then max_mark:=recnum;
  583.     show_log(rec,TRUE,TRUE);
  584.   end;
  585.  
  586.   procedure do_unmark(display:boolean);
  587.   begin
  588.     x_pos:=wherex; y_pos:=wherey;
  589.     max_mark:=0;
  590.     min_mark:=MAXREC + 1;
  591.     if display then show_log(rec,TRUE,TRUE);
  592.   end;
  593.  
  594.   procedure do_undelete;
  595.   var t,recnum:integer;
  596.       x_pos,y_pos:integer;
  597.       dummy:boolean;
  598.       i,j:integer;
  599.       ch:char;
  600.   begin
  601.     write_prompt('uNdelete:  Type "y" to continue');
  602.     ch:=upcase(fetch);
  603.     cmd_prompt(prompt_num);
  604.     bottom_window;
  605.     if ch <> 'Y' then exit;
  606.     x_pos:=wherex; y_pos:=wherey;
  607.     recnum:=rec - 1;
  608.     dummy:=precess(recnum,y_pos);
  609.     i:=records;
  610.  
  611.     while (i > 1) and (recdata.recstat[recdata.recptr[i]] <> DELETED)
  612.       do i:=i - 1;
  613.     if recdata.recstat[recdata.recptr[i]] = DELETED then { found one }
  614.       begin
  615.         t:=recdata.recptr[i];
  616.         recdata.recstat[t]:=SHOW;
  617.         for j:=i downto recnum + 1 do
  618.           recdata.recptr[j]:=recdata.recptr[j - 1];
  619.         recdata.recptr[recnum]:=t;
  620.         put_recdata(loglist.currentlog,recdata);
  621.         show_log(rec,TRUE,TRUE);
  622.       end;
  623.   end;
  624.  
  625.   procedure do_sort(auto:boolean);
  626.   var sortdata:sort_array_type;
  627.       subsortdata:sort_array_type;
  628.       primary,secondary:char;
  629.  
  630.     function get_sort_type(auto:boolean; var primary, secondary:char):boolean;
  631.     begin
  632.       if auto then { automatically do Frequency, Time sort }
  633.         begin
  634.           get_sort_type:=TRUE;
  635.           primary:='F';
  636.           secondary:='T';
  637.           exit;
  638.         end;
  639.       repeat
  640.         write_prompt('Sort - Primary field: D(ate, T(ime, F(req, C(all,'
  641.                      +' L(oc, M(ode, Q(uit');
  642.         primary:=upcase(fetch);
  643.       until primary in ['D','T','F','C','L','M','Q'];
  644.       if primary <> 'Q' then
  645.         repeat
  646.           write_prompt('Sort - Secondary field: D(ate, T(ime, F(req, C(all,'
  647.                      +' L(oc, M(ode, Q(uit');
  648.           secondary:=upcase(fetch);
  649.         until secondary in ['D','T','F','C','L','M','Q'];
  650.       cmd_prompt(prompt_num);
  651.       bottom_window;
  652.       get_sort_type:=(primary <> 'Q') and (secondary <> 'Q');
  653.     end;
  654.  
  655.     procedure get_fields;
  656.     var i:integer;
  657.         logdata:logtype;
  658.  
  659.       procedure init_array(var sortdata:short_str; cmd:char);
  660.       begin
  661.         case cmd of
  662.           'D':sortdata:=copy(logdata.date,1,SHORTSTRLEN);
  663.           'T':sortdata:=copy(logdata.begin_time,1,SHORTSTRLEN);
  664.           'F':str(logdata.frequency:8:1,sortdata);
  665.           'C':sortdata:=copy(logdata.callsign,1,SHORTSTRLEN);
  666.           'L':sortdata:=copy(logdata.location,1,SHORTSTRLEN);
  667.           'M':case logdata.mode of
  668.                 RTTY:sortdata:='RTTY';
  669.                 CW  :sortdata:='CW';
  670.                 USB :sortdata:='USB';
  671.                 LSB :sortdata:='LSB';
  672.                 AM  :sortdata:='AM';
  673.                 FM  :sortdata:='FM';
  674.                 FAX :sortdata:='FAX';
  675.                end;
  676.         end;
  677.       end;
  678.  
  679.     begin
  680.       home;
  681.       for i:=1 to records do
  682.       begin
  683.         if recdata.recstat[i] = DELETED then { dummy sort pos }
  684.           begin
  685.             sortdata[i]:=chr(255);
  686.             subsortdata[i]:=chr(255);
  687.           end
  688.         else
  689.           begin
  690.             get_log(logbuf,logdata,i);
  691.             init_array(sortdata[i],primary);
  692.             init_array(subsortdata[i],secondary);
  693.           end;
  694.         recdata.recptr[i]:=i;
  695.       end;
  696.     end;
  697.  
  698.     procedure primary_sort; { sort on primary field }
  699.     begin
  700.       write(output,'Primary sort');
  701.       sort(sortdata,recdata.recptr,1,records);
  702.     end;
  703.  
  704.     procedure secondary_sort; { sort on secondary field }
  705.     var i,top:integer;
  706.         tempstr:string;
  707.     begin
  708.       top:=1; home;
  709.       write(output,'Secondary sort');
  710.       while (top < records) do
  711.         begin
  712.           i:=0;
  713.           tempstr:=sortdata[top];
  714.           while (top + i < records) and (tempstr = sortdata[top + i]) do
  715.             begin
  716.               sortdata[top + i]:=subsortdata[recdata.recptr[top + i]];
  717.               inc(i);
  718.             end;
  719.           sort(sortdata,recdata.recptr,top,i);
  720.           top:=top + i;
  721.         end;
  722.     end;
  723.  
  724.   begin
  725.     if get_sort_type(auto,primary,secondary) then
  726.       begin
  727.         get_fields;
  728.         primary_sort;
  729.         secondary_sort;
  730.       end;
  731.     show_log(rec,TRUE,TRUE);
  732.     put_recdata(loglist.currentlog,recdata);
  733.   end;
  734.  
  735.   function upcasestr(s:string):string;
  736.   var i:integer;
  737.       s1:string;
  738.   begin
  739.     s1:=s;
  740.     for i:=1 to length(s) do s1[i]:=upcase(s[i]);
  741.     upcasestr:=s1;
  742.   end;
  743.  
  744.   procedure do_page;
  745.   begin
  746.     x_pos:=wherex; y_pos:=wherey;
  747.     display_page:=display_page + 1;
  748.     if display_page > 3 then display_page:=1;
  749.     draw_display_titles;
  750.     bottom_window;
  751.     if rslt = 0 then show_log(rec,TRUE,TRUE);
  752.   end;
  753.  
  754.   procedure do_tab;
  755.   begin
  756.     x_pos:=wherex; y_pos:=wherey;
  757.     case display_page of
  758.       1:begin
  759.           if x_pos in [1..5]   then x_pos:=6  else
  760.           if x_pos in [6..12]  then x_pos:=13 else
  761.           if x_pos in [13..17] then x_pos:=18 else
  762.           if x_pos in [18..22] then x_pos:=23 else
  763.           if x_pos in [23..31] then x_pos:=32 else
  764.           if x_pos in [32..51] then x_pos:=52 else
  765.             begin
  766.               x_pos:=11;
  767.               gotoxy(x_pos,y_pos);
  768.               do_page;
  769.             end;
  770.           gotoxy(x_pos,y_pos);
  771.         end;
  772.       2:begin
  773.           x_pos:=32;
  774.           gotoxy(x_pos,y_pos);
  775.           do_page;
  776.         end;
  777.       3:begin
  778.           if x_pos in [1..5]   then x_pos:=6  else
  779.           if x_pos in [6..12]  then x_pos:=13 else
  780.           if x_pos in [13..17] then x_pos:=18 else
  781.           if x_pos in [18..22] then x_pos:=23 else
  782.           if x_pos in [23..31] then x_pos:=32 else
  783.           if x_pos in [32..36] then x_pos:=37 else
  784.           if x_pos in [37..42] then x_pos:=43 else
  785.           if x_pos in [43..48] then x_pos:=49 else
  786.             begin
  787.               x_pos:=6;
  788.               gotoxy(x_pos,y_pos);
  789.               do_page;
  790.             end;
  791.           gotoxy(x_pos,y_pos);
  792.         end;
  793.     end;
  794.   end;
  795.  
  796.   procedure do_backtab;
  797.   begin
  798.     x_pos:=wherex; y_pos:=wherey;
  799.     case display_page of
  800.       1:begin
  801.           if x_pos in [7..13]  then x_pos:=6  else
  802.           if x_pos in [14..18] then x_pos:=13 else
  803.           if x_pos in [19..23] then x_pos:=18 else
  804.           if x_pos in [24..32] then x_pos:=23 else
  805.           if x_pos in [33..80] then x_pos:=32 else
  806.             begin
  807.               x_pos:=38;
  808.               gotoxy(x_pos,y_pos);
  809.               display_page:=display_page - 2;
  810.               do_page;
  811.             end;
  812.           gotoxy(x_pos,y_pos);
  813.         end;
  814.       2:begin
  815.           if x_pos in [3..10]  then x_pos:=2  else
  816.           if x_pos in [12..80] then x_pos:=11 else
  817.             begin
  818.               x_pos:=52;
  819.               gotoxy(x_pos,y_pos);
  820.               display_page:=display_page - 2;
  821.               do_page;
  822.             end;
  823.           gotoxy(x_pos,y_pos);
  824.         end;
  825.       3:begin
  826.           if x_pos in [7..13]  then x_pos:=6  else
  827.           if x_pos in [14..18] then x_pos:=13 else
  828.           if x_pos in [19..23] then x_pos:=18 else
  829.           if x_pos in [24..32] then x_pos:=23 else
  830.           if x_pos in [33..37] then x_pos:=32 else
  831.           if x_pos in [38..43] then x_pos:=37 else
  832.           if x_pos in [44..49] then x_pos:=43 else
  833.           if x_pos in [50..80] then x_pos:=49 else
  834.             begin
  835.               x_pos:=11;
  836.               gotoxy(x_pos,y_pos);
  837.               display_page:=display_page - 2;
  838.               do_page;
  839.             end;
  840.           gotoxy(x_pos,y_pos);
  841.         end;
  842.     end;
  843.   end;
  844.  
  845.   procedure do_edit; { edit field cursor is on }
  846.   var recnum:integer;
  847.       logdata:logtype;
  848.       s:string;
  849.       i,j,y,dummy:integer;
  850.       tabkey,backtabkey:boolean;
  851.  
  852.     procedure edit_page1;
  853.     begin
  854.       case x_pos of
  855.          6..12: editfield(5, y,DATELEN,FALSE,tabkey,backtabkey,logdata.date);
  856.         13..17: begin
  857.                   editfield(12,y,TIMELEN,FALSE,tabkey,backtabkey
  858.                                 ,logdata.begin_time);
  859.                   while length(logdata.begin_time) < 4 do
  860.                       logdata.begin_time:=concat('0',logdata.begin_time);
  861.                 end;
  862.         18..22: begin
  863.                   editfield(17,y,TIMELEN,FALSE,tabkey,backtabkey
  864.                                 ,logdata.end_time);
  865.                   while length(logdata.end_time) < 4 do
  866.                       logdata.end_time:=concat('0',logdata.end_time);
  867.                 end;
  868.         23..31: begin
  869.                   str(logdata.frequency:8:2,s);
  870.                   editfield(22,y,8,TRUE,tabkey,backtabkey,s);
  871.                   val(s,logdata.frequency,dummy);
  872.                 end;
  873.         32..51: editfield(31,y,CALLSIGNLEN,FALSE,tabkey,backtabkey
  874.                               ,logdata.callsign);
  875.         52..80: editfield(51,y,LOCATIONLEN,FALSE,tabkey,backtabkey
  876.                               ,logdata.location);
  877.       end;
  878.     end;
  879.  
  880.     procedure edit_page2;
  881.     begin
  882.       case x_pos of
  883.          1..10: begin
  884.                   str(logdata.frequency:8:2,s);
  885.                   editfield(1,y,8,TRUE,tabkey,backtabkey,s);
  886.                   val(s,logdata.frequency,dummy);
  887.                 end;
  888.         11..80: editfield(10,y,COMMENTLEN-1,FALSE,tabkey,backtabkey
  889.                               ,logdata.comment);
  890.       end;
  891.     end;
  892.  
  893.     procedure edit_page3;
  894.     begin
  895.       case x_pos of
  896.          6..12: editfield(5, y,DATELEN,FALSE,tabkey,backtabkey,logdata.date);
  897.         13..17: begin
  898.                   editfield(12,y,TIMELEN,FALSE,tabkey,backtabkey
  899.                                 ,logdata.begin_time);
  900.                   while length(logdata.begin_time) < 4 do
  901.                       logdata.begin_time:=concat('0',logdata.begin_time);
  902.                 end;
  903.         18..22: begin
  904.                   editfield(17,y,TIMELEN,FALSE,tabkey,backtabkey
  905.                                 ,logdata.end_time);
  906.                   while length(logdata.end_time) < 4 do
  907.                       logdata.end_time:=concat('0',logdata.end_time);
  908.                 end;
  909.         23..31: begin
  910.                   str(logdata.frequency:8:2,s);
  911.                   editfield(22,y,8,TRUE,tabkey,backtabkey,s);
  912.                   val(s,logdata.frequency,dummy);
  913.                 end;
  914.         32..36: begin
  915.                   case logdata.mode of
  916.                     RTTY: s:='RTTY';
  917.                     CW:   s:=' CW';
  918.                     USB:  s:='USB';
  919.                     LSB:  s:='LSB';
  920.                     AM:   s:=' AM';
  921.                     FM:   s:=' FM';
  922.                     FAX:  s:='FAX';
  923.                   end;
  924.                   editfield(31,y,4,FALSE,tabkey,backtabkey,s);
  925.                   s:=upcasestr(s);
  926.                   if pos('RTTY',s) > 0 then logdata.mode:=RTTY else
  927.                   if pos('CW',s)   > 0 then logdata.mode:=CW   else
  928.                   if pos('USB',s)  > 0 then logdata.mode:=USB  else
  929.                   if pos('LSB',s)  > 0 then logdata.mode:=LSB  else
  930.                   if pos('AM',s)   > 0 then logdata.mode:=AM   else
  931.                   if pos('FM',s)   > 0 then logdata.mode:=FM   else
  932.                   if pos('FAX',s)  > 0 then logdata.mode:=FAX
  933.                 end;
  934.         37..42: begin
  935.                   case logdata.bandwidth of
  936.                     NARR: s:=' NARR';
  937.                     INTER:s:='INTER';
  938.                     WIDE: s:=' WIDE';
  939.                     AUX:  s:=' AUX';
  940.                   end;
  941.                   editfield(36,y,5,FALSE,tabkey,backtabkey,s);
  942.                   s:=upcasestr(s);
  943.                   if pos('INTER',s) > 0 then logdata.bandwidth:=INTER else
  944.                   if pos('NARR',s)  > 0 then logdata.bandwidth:=NARR  else
  945.                   if pos('WIDE',s)  > 0 then logdata.bandwidth:=WIDE  else
  946.                   if pos('AUX' ,s)  > 0 then logdata.bandwidth:=AUX
  947.                 end;
  948.         43..48: begin
  949.                   case logdata.agc of
  950.                     FAST: s:='FAST';
  951.                     SLOW: s:='SLOW';
  952.                     OFF:  s:=' OFF';
  953.                   end;
  954.                   editfield(42,y,4,FALSE,tabkey,backtabkey,s);
  955.                   s:=upcasestr(s);
  956.                   if pos('FAST',s) > 0 then logdata.agc:=FAST else
  957.                   if pos('SLOW',s) > 0 then logdata.agc:=SLOW else
  958.                   if pos('OFF',s)  > 0 then logdata.agc:=OFF
  959.                 end;
  960.         49..51: begin
  961.                   case logdata.attenuator of
  962.                     YES: s:='ON';
  963.                     NO:  s:='OFF';
  964.                   end;
  965.                   editfield(48,y,3,FALSE,tabkey,backtabkey,s);
  966.                   s:=upcasestr(s);
  967.                   if pos('OFF',s) > 0 then logdata.attenuator:=NO else
  968.                   if pos('ON',s)  > 0 then logdata.attenuator:=YES
  969.                 end;
  970.       end;
  971.     end;
  972.  
  973.   begin { do_edit }
  974.     x_pos:=wherex; y_pos:=wherey; y:=y_pos - 1;
  975.     recnum:=rec - 1;
  976.     if precess(recnum,y_pos) then
  977.       begin
  978.         get_log(logbuf,logdata,recdata.recptr[recnum]);
  979.         case display_page of
  980.           1: edit_page1;
  981.           2: edit_page2;
  982.           3: edit_page3;
  983.         end;
  984.         put_log(logbuf,logdata,recdata.recptr[recnum]);
  985.         if not (tabkey or backtabkey) then
  986.           begin
  987.             gotoxy(x_pos,y_pos);
  988.             show_log(rec,TRUE,TRUE);
  989.           end;
  990.       end;
  991.     gotoxy(x_pos,y_pos);
  992.     if tabkey then
  993.       begin
  994.         do_tab;
  995.         do_edit;
  996.       end
  997.     else if backtabkey then
  998.       begin
  999.         do_backtab;
  1000.         do_edit;
  1001.       end;
  1002.   end;
  1003.  
  1004.   procedure do_delete;
  1005.   var x_pos,y_pos:integer;
  1006.       recnum:integer;
  1007.       ch:char;
  1008.       i,t:integer;
  1009.   begin
  1010.     x_pos:=wherex; y_pos:=wherey;
  1011.     recnum:=rec - 1;
  1012.     write_prompt('Delete:  Type "y" to continue');
  1013.     ch:=upcase(fetch);
  1014.     cmd_prompt(prompt_num);
  1015.     bottom_window;
  1016.     if ch = 'Y' then if precess(recnum,y_pos) then
  1017.       begin
  1018.         t:=recdata.recptr[recnum];
  1019.         recdata.recstat[t]:=DELETED;
  1020.         for i:=recnum to records - 1 do with recdata do
  1021.           recptr[i]:=recptr[i + 1];
  1022.         recdata.recptr[records]:=t;
  1023.         show_log(rec,TRUE,TRUE);
  1024.         put_recdata(loglist.currentlog,recdata);
  1025.       end;
  1026.   end;
  1027.  
  1028.   procedure do_log;
  1029.   var x_pos,y_pos:integer;
  1030.       t,recnum:integer;
  1031.       ch:char;
  1032.       i,j:integer;
  1033.       dummy:boolean;
  1034.       logdata:logtype;
  1035.   begin
  1036.     x_pos:=32; y_pos:=wherey;
  1037.     recnum:=rec - 1;
  1038.     dummy:=precess(recnum,y_pos);
  1039.     { get receiver status }
  1040.     if radio_type = 525 then remote_on else toggle_remote;
  1041.     show_receiver;
  1042.     remote_off(0);
  1043.     i:=1;
  1044.     while (i < records) and (recdata.recstat[recdata.recptr[i]] <> DELETED)
  1045.        do inc(i);
  1046.     if (i >= records) and (recdata.recstat[recdata.recptr[i]]<>DELETED) then
  1047.       { insert new entry here }
  1048.       begin
  1049.         inc(records);
  1050.         i:=records;
  1051.         recdata.recptr[i]:=i;
  1052.         loglist.log[loglist.currentlog].records:=records;
  1053.         put_loglist(loglist);
  1054.       end;
  1055.     t:=recdata.recptr[i];
  1056.     if recnum = 0 then recnum:=1; { special case for new arrays }
  1057.     for j:=i downto recnum + 1 do with recdata do
  1058.       recptr[j]:=recptr[j - 1];
  1059.     recdata.recptr[recnum]:=t;
  1060.     recdata.recstat[t]:=SHOW;
  1061.     clear_log(logdata);
  1062.     with receiverstat do
  1063.       begin
  1064.         if map then {center frequency}
  1065.           begin
  1066.             logdata.frequency:=trunc(frequency/5.0 + 0.5) * 5;
  1067.             logdata.mode:=USB;
  1068.             logdata.bandwidth:=INTER;
  1069.           end
  1070.         else
  1071.           begin
  1072.             logdata.frequency:=frequency;
  1073.             logdata.mode:=mode;
  1074.             logdata.bandwidth:=bandwidth;
  1075.           end;
  1076.         logdata.agc:=agc;
  1077.         logdata.attenuator:=attenuator;
  1078.       end;
  1079.     put_log(logbuf,logdata,recdata.recptr[recnum]);
  1080.     put_recdata(loglist.currentlog,recdata);
  1081.     if display_page <> 1 then
  1082.       begin
  1083.         display_page:=1;
  1084.         draw_display_titles;
  1085.         bottom_window;
  1086.       end;
  1087.     gotoxy(x_pos,y_pos);
  1088.     show_log(rec,TRUE,TRUE);
  1089.     do_edit;
  1090.   end;
  1091.  
  1092.   procedure do_tune;
  1093.  
  1094.   { assign log entry at cursor location to radio }
  1095.  
  1096.   var recnum:integer;
  1097.       logdata:logtype;
  1098.   begin
  1099.    y_pos:=wherey;
  1100.    recnum:=rec - 1;
  1101.    if precess(recnum, y_pos) then
  1102.      begin
  1103.        get_log(logbuf,logdata,recdata.recptr[recnum]);
  1104.        program_radio(logdata);
  1105.        if radio_type = 535 then toggle_remote;
  1106.      end;
  1107.   end;
  1108.  
  1109.   function find_rec(rec:integer; freq:real):integer; { find record >= frequency }
  1110.   var j:integer;
  1111.       logdata:logtype;
  1112.       first_try, found:boolean;
  1113.   begin
  1114.     j:=rec - 20; { skip back enuf records to find start hopefully }
  1115.     if j < 0 then j:=0;
  1116.     found:=FALSE; first_try:=TRUE;
  1117.     while (j < records) and not found do
  1118.       begin
  1119.         if precess(j,1) then
  1120.           begin
  1121.             get_log(logbuf,logdata,recdata.recptr[j]);
  1122.             if first_try and (logdata.frequency > freq)
  1123.               then j:=0
  1124.               else found:=logdata.frequency >= freq;
  1125.             first_try:=FALSE;
  1126.           end;
  1127.       end;
  1128.     find_rec:=j;
  1129.   end;
  1130.  
  1131.   procedure inc_freq;
  1132.   var s:string;
  1133.       x_pos,y_pos,i:integer;
  1134.       orig_freq:real;
  1135.  
  1136.     procedure display(frequency:real); { find displayed line matching freq }
  1137.     var found,lt:boolean;
  1138.         j:integer;
  1139.     begin
  1140.       j:=0; found:=FALSE; lt:=FALSE;
  1141.       while (j < LINES - REC_WIN_Y_BOTTOM - 1) and not found do
  1142.         begin
  1143.           inc(j);
  1144.           if frequency > displayed_freq[j] then lt:=TRUE; {condition for fnd}
  1145.           found:=frequency <= displayed_freq[j];
  1146.         end;
  1147.       if found and lt then { found it and its on the screen }
  1148.         begin
  1149.           y_pos:=j;
  1150.           gotoxy(x_pos,y_pos);
  1151.           show_log(rec,FALSE,TRUE);
  1152.         end
  1153.       else { new screen }
  1154.         begin
  1155.           rec:=find_rec(rec, frequency);
  1156.           gotoxy(x_pos,1);
  1157.           show_log(rec,TRUE,TRUE);
  1158.         end;
  1159.     end;
  1160.  
  1161.   begin {inc_freq}
  1162.     x_pos:=wherex; y_pos:=wherey;
  1163.     show_log(rec,FALSE,FALSE); { unhighlight current cursor line }
  1164.     with receiverstat do
  1165.       begin
  1166.         remote_on;
  1167.         orig_freq:=frequency;
  1168.         frequency:=trunc(frequency/10.0) * 10.0;
  1169.         if orig_freq - frequency >= 5.0 then frequency:=frequency + 5.0;
  1170.         case mode of
  1171.           USB: set_freq(frequency + 4.0);
  1172.           LSB: set_freq(frequency + 6.0);
  1173.           AM:
  1174.           else
  1175.             begin
  1176.               for i:=1 to 4 do
  1177.                 begin
  1178.                   set_freq(frequency + i);
  1179.                   delay(150);
  1180.                 end;
  1181.             end;
  1182.         end;
  1183.         delay(200);
  1184.         frequency:=frequency + 5.0;
  1185.         if map then frequency:=frequency + MAP_OFFSET;
  1186.         set_freq(frequency);
  1187.         remote_off(0);
  1188.         if radio_type = 535 then toggle_remote;
  1189.         show_receiver;
  1190.         display(frequency);
  1191.       end;
  1192.   end;
  1193.  
  1194.   procedure dec_freq;
  1195.   var s:string;
  1196.       x_pos,y_pos,i:integer;
  1197.       orig_freq:real;
  1198.  
  1199.     procedure display(frequency:real); { find displayed line matching freq }
  1200.     var found,lt:boolean;
  1201.         j:integer;
  1202.     begin
  1203.       j:=LINES - REC_WIN_Y_BOTTOM; found:=FALSE; lt:=FALSE;
  1204.       while (j > 1) and not found do
  1205.         begin
  1206.           dec(j);
  1207.           if frequency < displayed_freq[j] then lt:=TRUE;{condition for fnd}
  1208.           found:=frequency >= displayed_freq[j];
  1209.         end;
  1210.       if found and lt then { found it and its on the screen }
  1211.         begin
  1212.           gotoxy(x_pos,j);
  1213.           show_log(rec,FALSE,TRUE);
  1214.         end
  1215.       else { new screen }
  1216.         begin
  1217.           rec:=find_rec(rec, frequency);
  1218.           rec:=rec - LINES + REC_WIN_Y_BOTTOM + 2;
  1219.           if rec < 1 then rec:=1;
  1220.           gotoxy(x_pos,1);
  1221.           show_log(rec,TRUE,TRUE);
  1222.           show_log(rec,FALSE,FALSE);
  1223.           y_pos:=0; found:=FALSE;
  1224.           while not found and (y_pos < LINES - REC_WIN_Y_BOTTOM - 1) do
  1225.             begin
  1226.               inc(y_pos);
  1227.               found:=displayed_freq[y_pos] >=frequency;
  1228.             end;
  1229.           gotoxy(x_pos,y_pos);
  1230.           show_log(rec,FALSE,TRUE);
  1231.         end;
  1232.     end;
  1233.  
  1234.   begin {dec_freq}
  1235.     x_pos:=wherex; y_pos:=wherey;
  1236.     show_log(rec,FALSE,FALSE); { unhighlight current cursor line }
  1237.     with receiverstat do
  1238.       begin
  1239.         remote_on;
  1240.         orig_freq:=frequency;
  1241.         frequency:=trunc(frequency/10.0) * 10.0;
  1242.         if orig_freq - frequency > 5.0 then frequency:=frequency + 10.0
  1243.         else if orig_freq - frequency > 0.0 then frequency:=frequency + 5.0;
  1244.         case mode of
  1245.           USB: set_freq(frequency - 6.0);
  1246.           LSB: set_freq(frequency - 4.0);
  1247.           AM:
  1248.           else
  1249.             begin
  1250.               for i:=1 to 4 do
  1251.                 begin
  1252.                   set_freq(frequency - i);
  1253.                   delay(150);
  1254.                 end;
  1255.             end;
  1256.         end;
  1257.         delay(200);
  1258.         frequency:=frequency - 5.0;
  1259.         if map then frequency:= frequency + MAP_OFFSET;
  1260.         set_freq(frequency);
  1261.         remote_off(0);
  1262.         if radio_type = 535 then toggle_remote;
  1263.         show_receiver;
  1264.         display(receiverstat.frequency);
  1265.       end;
  1266.   end;
  1267.  
  1268.   procedure find_freq;
  1269.   var s:string;
  1270.       x_pos,y_pos,i:integer;
  1271.       orig_freq:real;
  1272.       ch:char;
  1273.  
  1274.     procedure display(frequency:real); { find displayed line matching freq }
  1275.     var found:boolean;
  1276.     begin
  1277.       rec:=find_rec(1, frequency);
  1278.       rec:=rec - LINES + REC_WIN_Y_BOTTOM + 2;
  1279.       if rec < 1 then rec:=1;
  1280.       gotoxy(x_pos,1);
  1281.       show_log(rec,TRUE,TRUE);
  1282.       show_log(rec,FALSE,FALSE);
  1283.       y_pos:=0; found:=FALSE;
  1284.       while not found and (y_pos < LINES - REC_WIN_Y_BOTTOM - 1) do
  1285.         begin
  1286.           inc(y_pos);
  1287.           found:=displayed_freq[y_pos] >=frequency;
  1288.         end;
  1289.       gotoxy(x_pos,y_pos);
  1290.       show_log(rec,FALSE,TRUE);
  1291.     end;
  1292.  
  1293.   begin {find_freq}
  1294.     x_pos:=wherex; y_pos:=wherey;
  1295.     show_log(rec,FALSE,FALSE); { unhighlight current cursor line }
  1296.     with receiverstat do
  1297.       begin
  1298.         if radio_type = 525 then remote_on
  1299.         else toggle_remote;
  1300.         remote_off(0);
  1301.         show_receiver;
  1302.         display(receiverstat.frequency);
  1303.       end;
  1304.   end;
  1305.  
  1306.   procedure inc_mode;
  1307.   var x_pos,y_pos:integer;
  1308.   begin
  1309.     x_pos:=wherex; y_pos:=wherey;
  1310.     with receiverstat do
  1311.       begin
  1312.         remote_on;
  1313.         if radio_type = 525 then
  1314.           begin
  1315.             if mode < FAX
  1316.               then mode:=succ(mode)
  1317.               else mode:=RTTY;
  1318.           end
  1319.         else { do special case for nrd535 }
  1320.           begin
  1321.             case mode of
  1322.                   RTTY: mode:=CW;
  1323.                     CW: mode:=USB;
  1324.                    USB: mode:=LSB;
  1325.                    LSB: mode:=AM;
  1326.                     AM: mode:=ECSS_USB; { change order }
  1327.               ECSS_USB: mode:=ECSS_LSB;
  1328.               ECSS_LSB: mode:=FM;
  1329.                     FM: mode:=FAX;
  1330.                    FAX: mode:=RTTY;
  1331.             end;
  1332.           end;
  1333.         set_mode(mode);
  1334.         remote_off(REMOTE_DLY + 100);
  1335.         if radio_type = 535 then toggle_remote;
  1336.         show_receiver;
  1337.         gotoxy(x_pos,y_pos);
  1338.       end;
  1339.   end;
  1340.  
  1341.   procedure dec_mode;
  1342.   var x_pos,y_pos:integer;
  1343.   begin
  1344.     x_pos:=wherex; y_pos:=wherey;
  1345.     with receiverstat do
  1346.       begin
  1347.         remote_on;
  1348.         if radio_type = 525 then
  1349.           begin
  1350.             if mode > RTTY
  1351.               then mode:=pred(mode)
  1352.               else mode:=FAX;
  1353.           end
  1354.         else { do special case for nrd535 }
  1355.           begin
  1356.             case mode of
  1357.                   RTTY: mode:=FAX;
  1358.                     CW: mode:=RTTY;
  1359.                    USB: mode:=CW;
  1360.                    LSB: mode:=USB;
  1361.                     AM: mode:=LSB;
  1362.               ECSS_USB: mode:=AM;
  1363.               ECSS_LSB: mode:=ECSS_USB;
  1364.                     FM: mode:=ECSS_LSB;
  1365.                    FAX: mode:=FM;
  1366.             end;
  1367.           end;
  1368.         set_mode(mode);
  1369.         remote_off(REMOTE_DLY + 100);
  1370.         if radio_type = 535 then toggle_remote;
  1371.         show_receiver;
  1372.         gotoxy(x_pos,y_pos);
  1373.       end;
  1374.   end;
  1375.  
  1376.   procedure inc_bandwidth;
  1377.   begin
  1378.     with receiverstat do
  1379.       begin
  1380.         remote_on;
  1381.         bandwidth:=succ(bandwidth);
  1382.         set_bandwidth(bandwidth);
  1383.         remote_off(REMOTE_DLY);
  1384.         if radio_type = 535 then toggle_remote;
  1385.         show_receiver;
  1386.       end;
  1387.   end;
  1388.  
  1389.   procedure dec_bandwidth;
  1390.   begin
  1391.     with receiverstat do
  1392.       begin
  1393.         remote_on;
  1394.         bandwidth:=pred(bandwidth);
  1395.         set_bandwidth(bandwidth);
  1396.         remote_off(REMOTE_DLY);
  1397.         if radio_type = 535 then toggle_remote;
  1398.         show_receiver;
  1399.       end;
  1400.   end;
  1401.  
  1402.   procedure do_kiwa; { different mode if KIWA MAP unit in use }
  1403.   var freq,offset:real;
  1404.       x_pos,y_pos:integer;
  1405.   begin
  1406.     x_pos:=wherex; y_pos:=wherey;
  1407.     map:=not map; {toggle mode}
  1408.     with receiverstat do
  1409.       begin
  1410.         if map then {enable mode}
  1411.           begin
  1412.             if mode = USB then offset:=MAP_OFFSET else offset:=-MAP_OFFSET;
  1413.             remote_on;
  1414.             set_mode(AM);
  1415.             mode:=AM;
  1416.             set_bandwidth(WIDE);
  1417.             bandwidth:=WIDE;
  1418.             set_agc(FAST);
  1419.             agc:=FAST;
  1420.             frequency:=trunc(frequency / 5.0 + 0.5) * 5.0 + offset;
  1421.             set_freq(frequency);
  1422.             remote_off(REMOTE_DLY);
  1423.           end
  1424.         else
  1425.           begin
  1426.             remote_on;
  1427.             freq:=frequency;
  1428.             frequency:=trunc(frequency / 5.0 + 0.5) * 5.0;
  1429.             set_freq(frequency);
  1430.             if frequency < freq then
  1431.               begin
  1432.                 set_mode(USB);
  1433.                 mode:=USB;
  1434.               end
  1435.             else
  1436.               begin
  1437.                 set_mode(LSB);
  1438.                 mode:=LSB;
  1439.               end;
  1440.             set_bandwidth(INTER);
  1441.             bandwidth:=INTER;
  1442.           end;
  1443.         remote_off(REMOTE_DLY);
  1444.       end;
  1445.     show_receiver;
  1446.     gotoxy(x_pos,y_pos);
  1447.   end;
  1448.  
  1449.   procedure do_confirm;
  1450.  
  1451.   { refresh database time and date and receiver status }
  1452.  
  1453.   var recnum:integer;
  1454.       tlog,logdata:logtype;
  1455.       t_begin, t_end, t_now, dummy:integer;
  1456.       ch:char;
  1457.       s:string;
  1458.   begin
  1459.    x_pos:=wherex; y_pos:=wherey;
  1460.    { get receiver status }
  1461.    if radio_type = 525 then remote_on
  1462.    else
  1463.      begin
  1464.        toggle_remote;
  1465.        if async_buffer_check(ch) then check_status(s);
  1466.      end;
  1467.    show_receiver;
  1468.    remote_off(0);
  1469.    recnum:=rec - 1;
  1470.    if precess(recnum, y_pos) then
  1471.      begin
  1472.       clear_log(tlog);
  1473.       get_log(logbuf,logdata,recdata.recptr[recnum]);
  1474.       write_prompt('Confirm:  Type "y" to continue');
  1475.       ch:=upcase(fetch);
  1476.       cmd_prompt(prompt_num);
  1477.       if ch = 'Y' then
  1478.         begin
  1479.           logdata.date:=tlog.date;
  1480.           val(tlog.begin_time,t_now,dummy);
  1481.           val(logdata.begin_time,t_begin,dummy);
  1482.           val(logdata.end_time,t_end,dummy);
  1483.           t_begin:=t_begin - t_now;
  1484.           if t_begin < 0 then t_begin:=t_begin + 2400;
  1485.           t_end:=t_now - t_end;
  1486.           if t_end < 0 then t_end:=t_end + 2400;
  1487.           if t_begin < t_end
  1488.              then if t_begin < 1200 then logdata.begin_time:=tlog.begin_time;
  1489.           if t_end < t_begin
  1490.              then if t_end < 1200 then logdata.end_time:=tlog.begin_time;
  1491.           with receiverstat do
  1492.             begin
  1493.               if not map then {don't update receiver params if using map}
  1494.                 begin
  1495.                   logdata.frequency:=frequency;
  1496.                   logdata.mode:=mode;
  1497.                   logdata.agc:=agc;
  1498.                   logdata.attenuator:=attenuator;
  1499.                   logdata.bandwidth:=bandwidth;
  1500.                 end;
  1501.             end;
  1502.           put_log(logbuf,logdata,recdata.recptr[recnum]);
  1503.         end;
  1504.       end;
  1505.    bottom_window;
  1506.    show_log(rec,TRUE,TRUE);
  1507.   end;
  1508.  
  1509.   procedure do_write; { as in dudley... }
  1510.   { copy record at cursor in inactive log to current log }
  1511.   var x_pos,y_pos:integer;
  1512.       t,recnum:integer;
  1513.       ch:char;
  1514.       i,j:integer;
  1515.       dummy:boolean;
  1516.   begin
  1517.     if last_log = 0 then exit;
  1518.     x_pos:=wherex; y_pos:=wherey;
  1519.     recnum:=rec - 1;
  1520.     dummy:=precess(recnum,y_pos);
  1521.     i:=1;
  1522.     while (i < records) and (recdata.recstat[recdata.recptr[i]] <> DELETED)
  1523.        do inc(i);
  1524.     if (i >= records) and (recdata.recstat[recdata.recptr[i]]<>DELETED) then
  1525.       { insert new entry here }
  1526.       begin
  1527.         inc(records);
  1528.         i:=records;
  1529.         recdata.recptr[i]:=i;
  1530.         loglist.log[loglist.currentlog].records:=records;
  1531.         put_loglist(loglist);
  1532.       end;
  1533.     t:=recdata.recptr[i];
  1534.     if recnum = 0 then recnum:=1; { special case for new arrays }
  1535.     for j:=i downto recnum + 1 do with recdata do
  1536.       recptr[j]:=recptr[j - 1];
  1537.     recdata.recptr[recnum]:=t;
  1538.     recdata.recstat[t]:=SHOW;
  1539.     put_log(logbuf,last_log_data,recdata.recptr[recnum]);
  1540.     put_recdata(loglist.currentlog,recdata);
  1541.     if display_page <> 1 then
  1542.       begin
  1543.         display_page:=1;
  1544.         draw_display_titles;
  1545.         bottom_window;
  1546.       end;
  1547.     gotoxy(x_pos,y_pos);
  1548.     show_log(rec,TRUE,TRUE);
  1549.   end;
  1550.  
  1551.   procedure do_pageup(cnt:byte);
  1552.   var i,j:integer;
  1553.   begin
  1554.     x_pos:=wherex; y_pos:=LINES - REC_WIN_Y_BOTTOM - 1;
  1555.     gotoxy(x_pos,y_pos);
  1556.     for j:=1 to cnt do
  1557.       begin
  1558.         for i:=1 to LINES - REC_WIN_Y_BOTTOM + 1 do
  1559.           begin
  1560.             if rec > 1 then rec:=rec - 1;
  1561.             while (rec > 1) and (recdata.recstat[recdata.recptr[rec]]
  1562.                                     <> SHOW) do
  1563.               rec:=rec - 1;
  1564.           end;
  1565.       end;
  1566.     if rslt = 0 then show_log(rec,TRUE,TRUE);
  1567.   end;
  1568.  
  1569.   procedure do_pagedown(cnt:byte);
  1570.   var i:integer;
  1571.   begin
  1572.     x_pos:=wherex; y_pos:=1;
  1573.     gotoxy(x_pos,y_pos);
  1574.     for i:=1 to cnt do
  1575.       if precess(rec, LINES - REC_WIN_Y_BOTTOM - 1) then
  1576.           if rec > records then rec:=records;
  1577.     if rslt = 0 then show_log(rec,TRUE,TRUE);
  1578.   end;
  1579.  
  1580.   procedure do_up;
  1581.   begin
  1582.     x_pos:=wherex; y_pos:=wherey;
  1583.     y_pos:=y_pos - 1;
  1584.     if y_pos < 1 then
  1585.       begin
  1586.         y_pos:=1;
  1587.         if rec > 1 then rec:=rec - 1;
  1588.         while (rec > 1) and (recdata.recstat[rec] <> SHOW) do
  1589.           rec:=rec - 1;
  1590.         if rslt = 0 then show_log(rec,TRUE,TRUE);
  1591.       end
  1592.     else
  1593.       begin
  1594.         show_log(rec,FALSE,FALSE);
  1595.         gotoxy(x_pos,y_pos);
  1596.         show_log(rec,FALSE,TRUE);
  1597.       end;
  1598.   end;
  1599.  
  1600.   procedure do_down;
  1601.   var dummy:boolean;
  1602.   begin
  1603.     x_pos:=wherex; y_pos:=wherey;
  1604.     inc(y_pos);
  1605.     if y_pos > LINES - REC_WIN_Y_BOTTOM - 1 then
  1606.      begin
  1607.        y_pos:=LINES - REC_WIN_Y_BOTTOM - 1;
  1608.        dummy:=precess(rec,1);
  1609.        if rec > records then rec:=records;
  1610.        if rslt = 0 then show_log(rec,TRUE,TRUE);
  1611.      end
  1612.     else
  1613.       begin
  1614.         show_log(rec,FALSE,FALSE);
  1615.         gotoxy(x_pos,y_pos);
  1616.         show_log(rec,FALSE,TRUE);
  1617.       end;
  1618.   end;
  1619.  
  1620.   procedure do_right;
  1621.   begin
  1622.     x_pos:=wherex; y_pos:=wherey;
  1623.     inc(x_pos);
  1624.     if x_pos > CHARPERLINE then
  1625.       begin
  1626.         x_pos:=1;
  1627.         inc(display_page);
  1628.         if display_page > 3 then display_page:=1;
  1629.         draw_display_titles;
  1630.         bottom_window;
  1631.         if rslt = 0 then show_log(rec,TRUE,TRUE);
  1632.       end;
  1633.     gotoxy(x_pos,y_pos);
  1634.   end;
  1635.  
  1636.   procedure do_left;
  1637.   begin
  1638.     x_pos:=wherex; y_pos:=wherey;
  1639.     x_pos:=x_pos - 1;
  1640.     if x_pos < 1 then
  1641.       begin
  1642.         x_pos:=CHARPERLINE;
  1643.         display_page:=display_page - 1;
  1644.         if display_page < 1 then display_page:=3;
  1645.         draw_display_titles;
  1646.         bottom_window;
  1647.         if rslt = 0 then show_log(rec,TRUE,TRUE);
  1648.       end;
  1649.     gotoxy(x_pos,y_pos);
  1650.   end;
  1651.  
  1652.   procedure do_home;
  1653.   begin
  1654.     rec:=1; x_pos:=1; y_pos:=1;
  1655.     gotoxy(x_pos,y_pos);
  1656.     show_log(rec,TRUE,TRUE);
  1657.   end;
  1658.  
  1659.   procedure do_end;
  1660.   begin
  1661.     rec:=records; x_pos:=1; y_pos:=1;
  1662.     do_pagedown(1);
  1663.   end;
  1664.  
  1665.   procedure new_log(lognum:byte; var rslt:integer);
  1666.   begin
  1667.     open_log(logbuf,lognum, rslt);
  1668.     get_recdata(lognum, recdata);
  1669.     records:=loglist.log[lognum].records;
  1670.     rec:=loglist.log[lognum].rec;
  1671.   end;
  1672.  
  1673.   procedure do_alternate;
  1674.   var i:integer;
  1675.       recnum:integer;
  1676.       t_begin, t_end, t_now, dummy:integer;
  1677.   begin
  1678.     x_pos:=wherex; y_pos:=wherey;
  1679.     recnum:=rec - 1;
  1680.     sync_loglist;
  1681.     if last_log > 0 then
  1682.       begin
  1683.         new_log(loglist.currentlog,rslt);
  1684.         if precess(recnum, y_pos) then
  1685.           get_log(logbuf,last_log_data,recdata.recptr[recnum]);
  1686.         i:=last_log;
  1687.         last_log:=loglist.currentlog;
  1688.         loglist.currentlog:=i;
  1689.         put_loglist(loglist);
  1690.         do_unmark(FALSE);
  1691.         close(logbuf);
  1692.       end;
  1693.     status_window;
  1694.     bottom_window;
  1695.     get_loglist(loglist);
  1696.     new_log(loglist.currentlog,rslt);
  1697.     x_pos:=1; y_pos:=1;
  1698.     gotoxy(x_pos,y_pos);
  1699.     show_log(rec,TRUE,TRUE);
  1700.   end;
  1701.  
  1702.   procedure do_journal;
  1703.   var ch:char;
  1704.       new:byte;
  1705.  
  1706.     procedure clr_prompt;
  1707.     begin
  1708.       gotoxy(1,2); clreol;
  1709.     end;
  1710.  
  1711.     procedure do_select(s:string; var new:byte);
  1712.     var found,dummy1,dummy2:boolean;
  1713.         i:integer;
  1714.         ch:char;
  1715.         t,t1:string;
  1716.     begin
  1717.       repeat
  1718.         clr_prompt;
  1719.         write(output,'Enter log NAME ',s,' (Enter for none):');
  1720.         t:='';
  1721.         editfield(47,1,6,FALSE,dummy1,dummy2,t);
  1722.         t:=upcasestr(t);
  1723.  
  1724.         { search for duplicate }
  1725.         found:=FALSE;
  1726.         i:=0;
  1727.         while (i < MAXLOGS) and not found do
  1728.           begin
  1729.             inc(i);
  1730.             with loglist.log[i] do if t = logname then found:=TRUE;
  1731.           end;
  1732.         if not found and (t[1] <> ' ') then
  1733.           begin
  1734.             clr_prompt;
  1735.             write(output,'Log not found <SPACE> to continue:');
  1736.             ch:=fetch;
  1737.             clr_prompt;
  1738.           end;
  1739.       until found or (t[1] = ' ');
  1740.       if not found then i:=loglist.currentlog;
  1741.       new:=i;
  1742.       clr_prompt;
  1743.     end;
  1744.  
  1745.     procedure do_create;
  1746.     var i:integer;
  1747.         s:short_str;
  1748.         dummy1,dummy2,found:boolean;
  1749.         ch:char;
  1750.     begin
  1751.       s:='';
  1752.       repeat
  1753.         clr_prompt;
  1754.         write('Enter new log name: ');
  1755.         editfield(22,1,6,FALSE,dummy1,dummy2,s);
  1756.         s:=upcasestr(s);
  1757.  
  1758.         { search for duplicate }
  1759.         found:=FALSE;
  1760.         for i:=1 to MAXLOGS do
  1761.           if s = upcasestr(loglist.log[i].logname) then found:=TRUE;
  1762.         if found then
  1763.           begin
  1764.             clr_prompt;
  1765.             write(output,s,': Duplicate log name <SPACE> to continue:');
  1766.             ch:=fetch;
  1767.             clr_prompt;
  1768.           end;
  1769.       until not found;
  1770.  
  1771.       { add name if not full }
  1772.       i:=0;
  1773.       while (i < MAXLOGS) and not found do
  1774.         begin
  1775.           i:=i + 1;
  1776.           if loglist.log[i].logname = '' then
  1777.             begin
  1778.               found:=TRUE;
  1779.               with loglist.log[i] do
  1780.                 begin
  1781.                   logname:=s;
  1782.                   records:=0;
  1783.                   rec:=1;
  1784.                 end;
  1785.               inc(loglist.logcount);
  1786.               put_loglist(loglist);
  1787.             end;
  1788.         end;
  1789.         if not found then
  1790.           begin
  1791.             clr_prompt;
  1792.             write(output,'Maximum number of logs exist <SPACE> to cont:');
  1793.             ch:=fetch;
  1794.             clr_prompt;
  1795.           end;
  1796.     end;
  1797.  
  1798.     procedure do_import;
  1799.     const db_name1 = 'SWSKED';
  1800.  
  1801.       procedure import(s:string);
  1802.       var found:boolean;
  1803.           rslt,i,j:integer;
  1804.           end_found:boolean;
  1805.  
  1806.         procedure move_db(logcnt:integer; var rslt:integer);
  1807.         var f:file;
  1808.             ch:char;
  1809.             i:integer;
  1810.             logdat:logtype;
  1811.             
  1812.           function read_file(chars:integer):string;
  1813.           var buf:array[1..255] of char;
  1814.               s:string;
  1815.               i:integer;
  1816.           begin
  1817.             rslt:=ioresult;
  1818.             s:='';
  1819.             if rslt <> 0 then read_file:=' '
  1820.             else
  1821.               begin
  1822.                 blockread(f,buf,chars);
  1823.                 for i:=1 to chars do s:=s + upcase(buf[i]);
  1824.                 read_file:=s;
  1825.               end;
  1826.           end;
  1827.  
  1828.           procedure strip_header;
  1829.           var buf:array[1..610] of char;
  1830.           begin
  1831.             { strip off first 610 characters and discard }
  1832.             blockread(f,buf,610);
  1833.             rslt:=ioresult;
  1834.           end;
  1835.  
  1836.           procedure get_entry(logcnt:integer);
  1837.           var logdat: logtype;
  1838.               freqs:array[1..10] of real;
  1839.               comments:array[1..10] of string[COMMENTLEN];
  1840.               i:integer;
  1841.  
  1842.             procedure get_location;
  1843.             var s:string;
  1844.                 i:integer;
  1845.                 test:boolean;
  1846.  
  1847.               function str_compare(s1,s2:string):boolean;
  1848.               var i:integer;
  1849.                   match:boolean;
  1850.               begin
  1851.                 match:=length(s1) = length(s2);
  1852.                 if match then for i:=1 to length(s1) do
  1853.                   if match then match:= s1[i] = s2[i];
  1854.                 str_compare:=match;
  1855.               end;
  1856.  
  1857.             begin
  1858.               s:=read_file(20);
  1859.               end_found:= pos(chr(26),s) <> 0;
  1860.               while length(s) < LOCATIONLEN do s:=s + ' ';
  1861.               logdat.location:=s;
  1862.             end;
  1863.  
  1864.             procedure get_station_id;
  1865.             var s:string;
  1866.             begin
  1867.               s:=read_file(24);
  1868.               while length(s) < CALLSIGNLEN do s:=s + ' ';
  1869.               logdat.callsign:=s;
  1870.             end;
  1871.  
  1872.             procedure get_start_time;
  1873.             begin
  1874.               logdat.begin_time:=read_file(4);
  1875.             end;
  1876.  
  1877.             procedure get_end_time;
  1878.             begin
  1879.               logdat.end_time:=read_file(4);
  1880.             end;
  1881.  
  1882.             function  get_freq:real;
  1883.             var freq:real;
  1884.                 i:integer;
  1885.                 s:string;
  1886.             begin
  1887.               freq:=0.0;
  1888.               s:=read_file(5);
  1889.               for i:=1 to 5 do
  1890.                 begin
  1891.                   if (s[i] in ['0'..'9'])
  1892.                      then freq:=freq * 10 + (ord(s[i]) - ord('0'));
  1893.                 end;
  1894.               get_freq:=freq;
  1895.             end;
  1896.  
  1897.             procedure get_comment;
  1898.             var s:string;
  1899.                 i:integer;
  1900.                 ch:char;
  1901.  
  1902.               procedure parse_comment(var s:string);
  1903.               var num1,num2,i,j:integer;
  1904.                   ch,separator:char;
  1905.                   s1,cmd:string;
  1906.                   found:boolean;
  1907.  
  1908.                 procedure get_num(var s:string; var num:integer);
  1909.                 var i:integer;
  1910.                     found:boolean;
  1911.                 begin
  1912.                   num:=0;
  1913.                   found:=FALSE;
  1914.                   while not found do
  1915.                     begin
  1916.                       num:=num * 10 + ord(s[1]) - ord('0');
  1917.                       delete(s,1,1);
  1918.                       found:=(s = '') or not (s[1] in ['0'..'9']);
  1919.                     end;
  1920.                 end;
  1921.  
  1922.                 procedure get_next_comment(var str:string);
  1923.                 var i:integer;
  1924.                 begin
  1925.                   i:=pos('#',s) - 1;
  1926.                   if i<=0 then i:=length(s);
  1927.                   str:=copy(s,1,i);
  1928.                   delete(s,1,i);
  1929.                 end;
  1930.  
  1931.                 procedure do_range; { case: #n-m }
  1932.                 var i:integer;
  1933.                     str:string;
  1934.                 begin
  1935.                   get_next_comment(str);
  1936.                   for i:=num1 to num2 do comments[i]:=comments[i] + str;
  1937.                   { handle case #m-n,o,... }
  1938.                   if cmd <> '' then while cmd[1] = ',' do
  1939.                     begin
  1940.                       delete(cmd,1,1);
  1941.                       get_num(cmd,num1);
  1942.                       comments[num1]:=comments[num1] + str;
  1943.                     end;
  1944.                 end;
  1945.  
  1946.                 procedure do_list; { case: #n,o,p...}
  1947.                 var i:integer;
  1948.                     str:string;
  1949.                 begin
  1950.                   get_next_comment(str);
  1951.                   comments[num1]:=comments[num1] + str;
  1952.                   comments[num2]:=comments[num2] + str;
  1953.                   if cmd <> '' then while cmd[1] = ',' do
  1954.                     begin
  1955.                       delete(cmd,1,1);
  1956.                       get_num(cmd,num1);
  1957.                       comments[num1]:=comments[num1] + str;
  1958.                     end;
  1959.                 end;
  1960.  
  1961.                 procedure do_entry; { case: #n }
  1962.                 var str:string;
  1963.                 begin
  1964.                   get_next_comment(str);
  1965.                   comments[num1]:=comments[num1] + str;
  1966.                 end;
  1967.  
  1968.                 procedure do_both; { case: #n&m }
  1969.                 var i:integer;
  1970.                     str:string;
  1971.                 begin
  1972.                   get_next_comment(str);
  1973.                   comments[num1]:=comments[num1] + str;
  1974.                   comments[num2]:=comments[num2] + str;
  1975.                   if cmd <> '' then while cmd[1] = '&' do
  1976.                     begin
  1977.                       delete(cmd,1,1);
  1978.                       get_num(cmd,num1);
  1979.                       comments[num1]:=comments[num1] + str;
  1980.                     end;
  1981.                 end;
  1982.  
  1983.               begin { parse comment }
  1984.                 { check for comment unique to entries }
  1985.                 i:=pos('#',s);
  1986.                 if i = 0 then i:=length(s) + 1;
  1987.                 { copy message up to command to each comment }
  1988.                 s1:=copy(s,1,i - 1);
  1989.                 for j:=1 to 10 do comments[j]:=comments[j] + s1;
  1990.  
  1991.                 { get comments unique to entry eg #4&5 }
  1992.                 cmd:='';
  1993.                 j:=i + 1;
  1994.                 found:=FALSE;
  1995.                 while (j < length(s)) and not found do
  1996.                   begin
  1997.                     found:=s[j] in [' ','#'];
  1998.                     if not found then
  1999.                       begin
  2000.                         cmd:=cmd + s[j];
  2001.                         inc(j);
  2002.                       end;
  2003.                   end;
  2004.                 delete(s,1,j - 1);
  2005.  
  2006.                 { decode unique comments and assign }
  2007.                 {   known formats: #n, #n&m, #n,m,...,#n-m }
  2008.                 get_num(cmd,num1);
  2009.                 if cmd <> '' then
  2010.                   begin
  2011.                     separator:=cmd[1];
  2012.                     delete(cmd,1,1);
  2013.                     get_num(cmd,num2);
  2014.                   end;
  2015.                 case separator of
  2016.                   '-': do_range;
  2017.                   '&': do_both;
  2018.                   ',': do_list;
  2019.                   else do_entry;
  2020.                 end;
  2021.               end;
  2022.  
  2023.             begin { get_comment }
  2024.               for i:=1 to 10 do comments[i]:='';
  2025.               s:='Target:' + read_file(40);
  2026.               { parse comments for individual entries }
  2027.               while length(s) > 0 do parse_comment(s);
  2028.               for i:=1 to 10 do while length(comments[i]) < COMMENTLEN do
  2029.                  comments[i]:=comments[i] + ' ';
  2030.             end;
  2031.  
  2032.             procedure get_date;
  2033.             var s:string;
  2034.             begin
  2035.               s:=read_file(2); { discard decade ie 19 }
  2036.               logdat.date:=read_file(6);
  2037.             end;
  2038.  
  2039.             procedure skip;
  2040.             var dummy:string;
  2041.             begin
  2042.               dummy:=read_file(9);
  2043.             end;
  2044.  
  2045.           begin { get_entry }
  2046.             { set variables that won't change for the duration }
  2047.             with logdat do
  2048.               begin
  2049.                 agc:=FAST;
  2050.                 mode:=USB;
  2051.                 bandwidth:=INTER;
  2052.               end;
  2053.             get_location;
  2054.             if end_found then exit;
  2055.             get_station_id;
  2056.             get_start_time;
  2057.             get_end_time;
  2058.             for i:=1 to 10 do freqs[i]:=get_freq;
  2059.             get_comment;
  2060.             get_date;
  2061.             skip;
  2062.             for i:=1 to 10 do
  2063.               begin
  2064.                 if freqs[i] <> 0.0 then
  2065.                   begin
  2066.                     with loglist.log[logcnt] do
  2067.                       begin
  2068.                         inc(records);
  2069.                         write(output,'.');
  2070.                         if records < MAXREC then
  2071.                           begin
  2072.                             logdat.comment:=comments[i];
  2073.                             logdat.frequency:=freqs[i];
  2074.                             put_log(logbuf,logdat,records);
  2075.                           end;
  2076.                       end;
  2077.                   end;
  2078.               end;
  2079.           end;
  2080.  
  2081.         begin { move_db }
  2082.           assign(f,PATH+S+'.DBF');
  2083.           reset(f,1);
  2084.           rslt:=ioresult;
  2085.           if rslt <> 0 then
  2086.             begin
  2087.               writeln(output,
  2088.                    'Must have ',PATH+S+'.DBF in directory to import');
  2089.               hndlerr(TRUE,ch,rslt);
  2090.               exit;
  2091.             end;
  2092.           strip_header;
  2093.           home;
  2094.           write(output,'Reading / parsing database');
  2095.           end_found:=false;
  2096.           while (rslt = 0) and not end_found do get_entry(logcnt);
  2097.           close(f);
  2098.           records:=loglist.log[loglist.currentlog].records;
  2099.           for i:=1 to MAXREC do
  2100.             begin
  2101.               recdata.recptr[i]:=i;
  2102.               recdata.recstat[i]:=SHOW;
  2103.             end;
  2104.           put_recdata(loglist.currentlog,recdata);
  2105.           put_loglist(loglist);
  2106.           rslt:=0;
  2107.         end;
  2108.  
  2109.         procedure eliminate_dups(lognum:integer);
  2110.         { collapse entries with time overlap }
  2111.         var rec1ptr,i,j,t,rslt:integer;
  2112.             logdata1,logdata2:logtype;
  2113.         begin
  2114.           home;
  2115.           write(output,'Crunching duplicate entries');
  2116.           get_log(logbuf,logdata1,recdata.recptr[1]);
  2117.           rec1ptr:=1;
  2118.           i:=2;
  2119.           while (i < loglist.log[lognum].records) do
  2120.             begin
  2121.               if recdata.recstat[recdata.recptr[i]] = DELETED then exit;
  2122.               get_log(logbuf,logdata2,recdata.recptr[i]);
  2123.               write(output,'.');
  2124.               if (logdata2.frequency  = logdata1.frequency) and
  2125.                  (logdata2.begin_time = logdata1.end_time)  and
  2126.                  (logdata2.comment    = logdata1.comment)   and
  2127.                  (logdata2.location   = logdata1.location)  and
  2128.                  (logdata2.callsign   = logdata1.callsign) then
  2129.                 begin
  2130.                   logdata1.end_time:=logdata2.end_time;
  2131.                   put_log(logbuf,logdata1,recdata.recptr[rec1ptr]);
  2132.                   t:=recdata.recptr[i];
  2133.                   recdata.recstat[t]:=DELETED;
  2134.                   for j:=i to records - 1 do with recdata do
  2135.                      recptr[j]:=recptr[j + 1];
  2136.                   recdata.recptr[records]:=t;
  2137.                 end
  2138.               else { no match }
  2139.                 begin
  2140.                   logdata1:=logdata2;
  2141.                   rec1ptr:=i;
  2142.                   inc(i);
  2143.                 end;
  2144.             end;
  2145.         end;
  2146.  
  2147.       begin { import }
  2148.         found:=FALSE;
  2149.         i:=0;
  2150.         while not found and (i < MAXLOGS) do
  2151.           begin
  2152.             inc(i);
  2153.             if s = upcasestr(loglist.log[i].logname) then found:=TRUE;
  2154.           end;
  2155.         if found then
  2156.           begin
  2157.             with loglist.log[i] do
  2158.                begin
  2159.                  logname:=s;
  2160.                  records:=0;
  2161.                  rec:=1;
  2162.                end;
  2163.           end
  2164.         else { add name if not full }
  2165.           begin
  2166.             i:=0;
  2167.             while (i < MAXLOGS) and not found do
  2168.               begin
  2169.                 i:=i + 1;
  2170.                 if loglist.log[i].logname = '' then
  2171.                   begin
  2172.                     found:=TRUE;
  2173.                     inc(loglist.logcount);
  2174.                     put_loglist(loglist);
  2175.                   end;
  2176.               end;
  2177.             if not found then
  2178.               begin
  2179.                 clr_prompt;
  2180.                 write(output,'Maximum number of logs exist <SPACE> to cont:');
  2181.                 ch:=fetch;
  2182.                 clr_prompt;
  2183.                 exit;
  2184.               end;
  2185.             with loglist.log[i] do
  2186.                begin
  2187.                  logname:=s;
  2188.                  records:=0;
  2189.                  rec:=1;
  2190.                end;
  2191.           end;
  2192.         loglist.currentlog:=i;
  2193.         open_log(logbuf,i,rslt);
  2194.         move_db(i,rslt);
  2195.         if rslt = 0 then
  2196.           begin
  2197.             home;
  2198.             do_sort(TRUE);
  2199.             eliminate_dups(i);
  2200.             put_recdata(loglist.currentlog,recdata);
  2201.           end;
  2202.         close(logbuf);
  2203.       end;
  2204.  
  2205.     begin
  2206.       import(db_name1);
  2207.     end;
  2208.  
  2209.     procedure do_delete;
  2210.     var i:integer;
  2211.         s,s1:short_str;
  2212.         dummy1,dummy2,found:boolean;
  2213.         ch:char;
  2214.         f:file;
  2215.     begin
  2216.       clr_prompt; s:='';
  2217.       write('Enter log to DELETE: ');
  2218.       editfield(22,1,6,FALSE,dummy1,dummy2,s);
  2219.       s:=upcasestr(s);
  2220.  
  2221.       { search for entry }
  2222.       found:=FALSE;
  2223.       i:=0;
  2224.       while (i < MAXLOGS) and not found do
  2225.         begin
  2226.           inc(i);
  2227.           if s = upcasestr(loglist.log[i].logname) then found:=TRUE;
  2228.         end;
  2229.       if found then
  2230.         begin
  2231.           clr_prompt;
  2232.           write(output,'DELETE ',s,'?');
  2233.           ch:=upcase(fetch);
  2234.           clr_prompt;
  2235.           if ch = 'Y' then
  2236.             begin
  2237.               loglist.log[i].logname:='';
  2238.               loglist.log[i].records:=0;
  2239.               loglist.log[i].rec:=0;
  2240.               loglist.logcount:=loglist.logcount - 1;
  2241.               put_loglist(loglist);
  2242.               str(i,s1);
  2243.               if length(s1) = 1 then s1:='0' + s1;
  2244.               s1:=s1 + '.DAT';
  2245.               assign(f,PATH + RECDATAFILE + s1);
  2246.               erase(f);
  2247.               assign(f,PATH + LOGFILE + s1);
  2248.               erase(f);
  2249.             end;
  2250.         end;
  2251.     end;
  2252.  
  2253.     procedure display_logs;
  2254.     var i,j,k,deletions:integer;
  2255.         t:string;
  2256.         recdata:recdatatype;
  2257.     begin
  2258.       gotoxy(1,4);
  2259.       call_crt(ERASEOS);
  2260.       j:=0;
  2261.       for i:=1 to MAXLOGS do
  2262.         begin
  2263.           t:=loglist.log[i].logname;
  2264.           if t <> '' then { display it }
  2265.             begin
  2266.               inc(j);
  2267.               deletions:=0;
  2268.               get_recdata(i,recdata);
  2269.               for k:=1 to loglist.log[i].records do
  2270.                 if recdata.recstat[k] = DELETED then inc(deletions);
  2271.               writeln(output,j:3,'  ',t,' ',loglist.log[i].records
  2272.                                   - deletions);
  2273.             end;
  2274.         end;
  2275.     end;
  2276.  
  2277.     procedure move_record(marked, move:boolean; dest, from:byte);
  2278.     var x_pos,y_pos:integer;
  2279.       t,recnum:integer;
  2280.       ch:char;
  2281.       i,j:integer;
  2282.       dummy:boolean;
  2283.       logdata:logtype;
  2284.       to_recdata,from_recdata:recdatatype;
  2285.       found:boolean;
  2286.       from_buf,to_buf:file;
  2287.  
  2288.       function get_logentry(i:integer;var logdata:logtype):boolean;
  2289.       var found:boolean;
  2290.           j,k,l:integer;
  2291.       begin
  2292.         found:=TRUE;
  2293.         j:=from_recdata.recptr[i];
  2294.         if marked then found:=(i >=min_mark) and (i <=max_mark);
  2295.         found:=found and (from_recdata.recstat[j] = SHOW);
  2296.         if found then
  2297.           begin
  2298.             get_log(from_buf,logdata,j);
  2299.             if move then { delete old entry }
  2300.                 from_recdata.recstat[j]:=DELETED;
  2301.           end;
  2302.         get_logentry:=found;
  2303.       end;
  2304.  
  2305.       procedure put_logentry(var i:integer; logdata:logtype);
  2306.       var j:integer;
  2307.       begin
  2308.         while (i < loglist.log[dest].records)
  2309.           and (to_recdata.recstat[to_recdata.recptr[i]] <> DELETED)
  2310.                   do inc(i);
  2311.         if (i >= loglist.log[dest].records)
  2312.            and (to_recdata.recstat[to_recdata.recptr[i]] <> DELETED) then
  2313.         { insert new entry here }
  2314.           begin
  2315.             inc(loglist.log[dest].records);
  2316.             i:=loglist.log[dest].records;
  2317.             to_recdata.recptr[i]:=i;
  2318.             if recnum = 0 then recnum:=1;
  2319.           end;
  2320.         t:=to_recdata.recptr[i];
  2321.         for j:=i downto recnum + 1 do with to_recdata do
  2322.           recptr[j]:=recptr[j - 1];
  2323.         to_recdata.recptr[recnum]:=t;
  2324.         to_recdata.recstat[t]:=SHOW;
  2325.         put_log(to_buf,logdata,to_recdata.recptr[recnum]);
  2326.         inc(recnum);
  2327.       end;
  2328.  
  2329.       procedure push_delete;
  2330.       { push deleted records to the end of the chain }
  2331.       var i,j,k,last:integer;
  2332.       begin
  2333.         last:=loglist.log[from].records;
  2334.         for i:=1 to last do
  2335.           begin
  2336.             j:=from_recdata.recptr[i];
  2337.             if from_recdata.recstat[j] = DELETED then
  2338.               begin
  2339.                 for k:=i to last - 1 do
  2340.                   from_recdata.recptr[k]:=from_recdata.recptr[k + 1];
  2341.                 from_recdata.recptr[last]:=j;
  2342.               end;
  2343.           end;
  2344.       end;
  2345.  
  2346.     begin {move_record }
  2347.       recnum:=loglist.log[dest].rec;
  2348.       get_recdata(from,from_recdata);
  2349.       get_recdata(dest,to_recdata);
  2350.       open_log(from_buf,from,rslt); if rslt > 0 then exit;
  2351.       open_log(to_buf,dest,rslt);   if rslt > 0 then exit;
  2352.       j:=1;
  2353.       for i:=1 to loglist.log[from].records do
  2354.         begin
  2355.           found:=get_logentry(i,logdata);
  2356.           if found then put_logentry(j,logdata);
  2357.         end;
  2358.       if move then push_delete;
  2359.       close(to_buf);
  2360.       close(from_buf);
  2361.       put_recdata(dest,to_recdata);
  2362.       put_recdata(from,from_recdata);
  2363.       put_loglist(loglist);
  2364.     end;
  2365.  
  2366.     procedure do_the_write;
  2367.     var dest:byte;
  2368.     begin
  2369.       do_select('to write to',dest);
  2370.       move_record(TRUE,FALSE,dest,loglist.currentlog);
  2371.     end;
  2372.  
  2373.     procedure do_move;
  2374.     var dest:byte;
  2375.     begin
  2376.       do_select('to move to',dest);
  2377.       move_record(TRUE,TRUE,dest,loglist.currentlog);
  2378.       do_unmark(FALSE);
  2379.     end;
  2380.  
  2381.     procedure do_print;
  2382.  
  2383.     const LINESPERPAGE = 60;
  2384.  
  2385.     var pbuf:text;
  2386.         i,cnt:integer;
  2387.         dummy:boolean;
  2388.         logdata:logtype;
  2389.         s:short_str;
  2390.         s1:string;
  2391.         logbuf:file;
  2392.         rslt:integer;
  2393.  
  2394.       procedure printhdr;
  2395.       begin
  2396.         write(pbuf,'Num   Date  Strt End  Freq     '+
  2397.                           'Station ID          Location');
  2398.         writeln(pbuf,'Comment':22,'Md':35,' BW');
  2399.         cnt:=1;
  2400.       end;
  2401.  
  2402.     begin
  2403.       assign(pbuf,'LPT1');
  2404.       rewrite(pbuf);
  2405.       write(pbuf,chr(27),'g'); { compressed mode }
  2406.       printhdr;
  2407.       i:=0;
  2408.       open_log(logbuf,loglist.currentlog,rslt);
  2409.       while (i < records) do
  2410.         begin
  2411.           dummy:=precess(i,1);
  2412.           get_log(logbuf,logdata,recdata.recptr[i]);
  2413.           if (i >= min_mark) and (i <= max_mark) then
  2414.             begin
  2415.               inc(cnt);
  2416.               if cnt > LINESPERPAGE then
  2417.                 begin
  2418.                   write(pbuf,chr(12)); { form feed }
  2419.                   printhdr;
  2420.                 end;
  2421.               with logdata do
  2422.                 begin
  2423.                   write(pbuf,i:4,date:DATELEN + 1,begin_time:TIMELEN + 1);
  2424.                   write(pbuf,end_time:TIMELEN + 1);
  2425.                   write(pbuf,frequency:9:2,callsign:CALLSIGNLEN + 1);
  2426.                   s1:=copy(location,1,22);
  2427.                   while length(s1) < 22 do s1:=s1 + ' ';
  2428.                   write(pbuf,s1:23);
  2429.                   s1:=copy(comment,1,39);
  2430.                   while length(s1) < 39 do s1:=s1 + ' ';
  2431.                   write(pbuf,s1:40);
  2432.                   case mode of
  2433.                     RTTY:     s:='RT';
  2434.                     CW:       s:='CW';
  2435.                     USB:      s:='UB';
  2436.                     LSB:      s:='LB';
  2437.                     AM:       s:='AM';
  2438.                     FM:       s:='FM';
  2439.                     FAX:      s:='FX';
  2440.                     ECSS_USB: s:='Eu';
  2441.                     ECSS_LSB: s:='El';
  2442.                   end;
  2443.                   write(pbuf,s:3);
  2444.                   case bandwidth of
  2445.                     NARR:  s:='NR';
  2446.                     INTER: s:='IN';
  2447.                     WIDE:  s:='WD';
  2448.                     AUX:   s:='AX';
  2449.                   end;
  2450.                   writeln(pbuf,s:3);
  2451.                 end;
  2452.             end;
  2453.         end;
  2454.       close(pbuf);
  2455.       close(logbuf);
  2456.     end;
  2457.  
  2458.   begin
  2459.     sync_loglist;
  2460.     close(logbuf);
  2461.     repeat
  2462.       write_prompt('Journal: '+
  2463.       'S(elect, C(reate, D(el, I(mport, W(rite, M(ove, P(rint, Q(uit');
  2464.       bottom_window;
  2465.       home;
  2466.       display_logs;
  2467.       ch:=upcase(fetch);
  2468.       case ch of
  2469.         'S': begin
  2470.                do_select('to switch to',new);
  2471.                last_log:=new;
  2472.                if loglist.currentlog = last_log then last_log:=0;
  2473.                put_loglist(loglist);
  2474.                cmd_prompt(prompt_num);
  2475.                do_alternate;
  2476.                exit;
  2477.              end;
  2478.         'C': do_create;
  2479.         'D': do_delete;
  2480.         'W': do_the_write;
  2481.         'M': do_move;
  2482.         'P': do_print;
  2483.         'I': do_import;
  2484.       end;
  2485.     until (ch = 'Q');
  2486.     cmd_prompt(prompt_num);
  2487.     bottom_window;
  2488.     get_loglist(loglist);
  2489.     new_log(loglist.currentlog,rslt);
  2490.     x_pos:=1; y_pos:=1;
  2491.     gotoxy(x_pos,y_pos);
  2492.     show_log(rec,TRUE,TRUE);
  2493.   end;
  2494.  
  2495.   procedure call_do_help;
  2496.   begin
  2497.     do_help;
  2498.     show_log(rec,TRUE,TRUE);
  2499.   end;
  2500.  
  2501.   procedure check_s_meter(var reading:integer);
  2502.   var s:string;
  2503.       s_reading, dummy:integer;
  2504.       
  2505.   begin
  2506.     reading:=1;
  2507.     write_com(COM_NRD,'H1'); { lock radio; cmd mode }
  2508.     if async_buffer_check(ch) then comreadln(COM_NRD,s); { discard }
  2509.     write_com(COM_NRD,'M');  { request s-meter reading }
  2510.     write_com(COM_NRD,'H0'); { unlock radio }
  2511.     comreadln(COM_NRD,s);
  2512.     write_com(COM_NRD,'I1');
  2513.     if s[1] = 'M' then { got a valid s-meter reading }
  2514.       begin
  2515.         delete(s,1,1);
  2516.         val(s,s_reading,dummy);
  2517.         case s_reading of { map to dB }
  2518.           255..245: reading:=-9;
  2519.           244..233: reading:=-8;
  2520.           232..221: reading:=-7;
  2521.           220..209: reading:=-6;
  2522.           208..198: reading:=-5;
  2523.           197..186: reading:=-4;
  2524.           185..174: reading:=-3;
  2525.           173..163: reading:=-2;
  2526.           162..155: reading:=-1;
  2527.           154..163: reading:=1;
  2528.           142..155: reading:=2;
  2529.           133..143: reading:=3;
  2530.           124..134: reading:=4;
  2531.           118..125: reading:=5;
  2532.           112..119: reading:=6;
  2533.           108..113: reading:=7;
  2534.           103..109: reading:=8;
  2535.            99..104: reading:=9;
  2536.            92.. 98: reading:=10;
  2537.            90.. 91: reading:=15;
  2538.            87.. 89: reading:=20;
  2539.            84.. 86: reading:=25;
  2540.            81.. 83: reading:=30;
  2541.            78.. 80: reading:=35;
  2542.            75.. 77: reading:=40;
  2543.            73.. 74: reading:=45;
  2544.            72.. 72: reading:=50;
  2545.            70.. 71: reading:=55;
  2546.             0.. 69: reading:=60;
  2547.             else reading:=1;
  2548.         end;
  2549.     end;
  2550.   end;
  2551.  
  2552.   procedure timed_s_meter;
  2553.   var reading:integer;
  2554.       hour,minute,sec,sec100:word;
  2555.   begin
  2556.     x_pos:=wherex; y_pos:=wherey;
  2557.     if radio_type <> 535 then exit;
  2558.     gettime(hour,minute,sec,sec100);
  2559.     time_stamp:=sec;
  2560.     if (time_stamp <> old_time_stamp) then
  2561.       begin
  2562.         old_time_stamp:=time_stamp;
  2563.         check_s_meter(reading);
  2564.         top_window;
  2565.         gotoxy(42,3);
  2566.         writea(LIGHTGRAY,FOREGROUND);
  2567.         write(output,'S-Meter:');
  2568.         if (reading > 9)
  2569.           then writea(RED,FOREGROUND)
  2570.           else writea(CYAN,FOREGROUND);
  2571.         write(output,reading:2);
  2572.         bottom_window;
  2573.       end;
  2574.   end;
  2575.  
  2576.   procedure init_crt;
  2577.   begin
  2578.     home;
  2579.     init_rec_window;
  2580.     update_receiver_display:=TRUE;
  2581.     status_window;
  2582.     bottom_window;
  2583.   end;
  2584.  
  2585.   procedure graph_init;
  2586.   var graphdriver:integer;
  2587.       errorcode:integer;
  2588.   begin
  2589.     if radio_type = 525 then exit;
  2590.     graphdriver:=detect;
  2591.     case graphdriver of
  2592.       CGA:     graphmode:=CGAHI;
  2593.       MCGA:    graphmode:=MCGAHI;
  2594.       EGA:     graphmode:=EGAHI;
  2595.       EGA64:   graphmode:=EGA64HI;
  2596.       EGAMONO: graphmode:=EGAMONOHI;
  2597.       IBM8514: graphmode:=IBM8514HI;
  2598.       HERCMONO:graphmode:=HERCMONOHI;
  2599.       ATT400:  graphmode:=ATT400HI;
  2600.       VGA:     graphmode:=VGAHI;
  2601.       PC3270:  graphmode:=PC3270HI;
  2602.     end;
  2603.     initgraph(graphdriver,graphmode,'');
  2604.     errorcode:=graphresult;
  2605.     if errorcode <> grok then exit;
  2606.     restorecrtmode;
  2607.     home;
  2608.   end;
  2609.  
  2610.   procedure do_graph;
  2611.   const X_INIT    = 40;
  2612.         Y_INIT    = 100;
  2613.         SCALE     = 2.2;
  2614.         Y_SCALE   = 480;
  2615.         X_SCALE   = 640;
  2616.         X_AXIS    = X_INIT - 5;
  2617.  
  2618.   type plottype = (NONE, TIME, SPECTRAL);
  2619.  
  2620.   var count:integer;
  2621.       reading:integer;
  2622.       dummy:integer;
  2623.       max_x,max_y:integer;
  2624.       max_count:integer;
  2625.       hour,minute,sec,sec100:word;
  2626.       last_plot:plottype;
  2627.       ch:char;
  2628.       start_freq, stop_freq:real;
  2629.  
  2630.     function scale_y(reading:integer):integer;
  2631.     begin
  2632.       scale_y:=round((reading * SCALE - Y_INIT) * max_y / Y_SCALE);
  2633.     end;
  2634.  
  2635.     procedure init_graph;
  2636.     var y:integer;
  2637.  
  2638.       procedure draw_tick(reading:integer; db:string);
  2639.       var y:integer;
  2640.       begin
  2641.         y:=scale_y(reading);
  2642.         moveto(X_AXIS-2,y);
  2643.         lineto(X_AXIS+5,y);
  2644.         setcolor(8);
  2645.         lineto(max_x,y);
  2646.         setcolor(15);
  2647.         moveto(X_AXIS-30,y-3);
  2648.         outtext(db);
  2649.       end;
  2650.  
  2651.     begin
  2652.       setgraphmode(graphmode);
  2653.       moveto(X_AXIS,scale_y(240));
  2654.       lineto(X_AXIS,scale_y(60));
  2655.       draw_tick(67,'');
  2656.       draw_tick(71,'+50');
  2657.       draw_tick(75,'');
  2658.       draw_tick(81,'+30');
  2659.       draw_tick(87,'');
  2660.       draw_tick(92,'+10');
  2661.       draw_tick(99,'+9');
  2662.       draw_tick(108,'+7');
  2663.       draw_tick(118,'+5');
  2664.       draw_tick(133,'+3');
  2665.       draw_tick(154,'+1');
  2666.     end;
  2667.  
  2668.     function get_s_reading:integer;
  2669.     var s,s1:string;
  2670.         ch:char;
  2671.         reading:integer;
  2672.         freq:real;
  2673.     begin
  2674.       repeat
  2675.         write_com(COM_NRD,'M');  { request s-meter reading }
  2676.         comreadln(COM_NRD,s);
  2677.         ch:=s[1];
  2678.         delete(s,1,1);
  2679.         if ch = 'M' then val(s,reading,dummy);
  2680.       until ch = 'M';
  2681.       get_s_reading:=reading;
  2682.     end;
  2683.  
  2684.     procedure plot_title(s:string);
  2685.     begin
  2686.       setfillstyle(1,0);
  2687.       bar(100,18,max_x,25);
  2688.       moveto(((max_x - length(s)) div 2) - 25,18);
  2689.       outtext(S);
  2690.     end;
  2691.  
  2692.     procedure clear_prompt;
  2693.     begin
  2694.       setfillstyle(1,0);
  2695.       bar(1,1,max_x,8);
  2696.       setcolor(2);
  2697.       moveto(1,1);
  2698.     end;
  2699.  
  2700.     procedure out_prompt(s:string);
  2701.     begin
  2702.       clear_prompt;
  2703.       outtext(s);
  2704.       setcolor(15);
  2705.     end;
  2706.  
  2707.     procedure main_prompt;
  2708.     begin
  2709.       out_prompt('GRAPHICS: C(lear, T(ime plot, S(pectral plot, Q(uit');
  2710.     end;
  2711.  
  2712.     procedure time_plot;
  2713.     var ch:char;
  2714.     begin
  2715.       out_prompt('Hit <SPACE BAR> to stop');
  2716.       setfillstyle(1,0);
  2717.       bar(1,scale_y(238),getmaxx,scale_y(260));
  2718.       plot_title('T I M E  P L O T');
  2719.       count:=0;
  2720.       write_com(COM_NRD,'H1'); { lock radio; cmd mode }
  2721.       reading:=get_s_reading;
  2722.       moveto(X_INIT,scale_y(reading));
  2723.       setcolor(11);
  2724.       while not keypressed do
  2725.         begin
  2726.           gettime(hour,minute,sec,sec100);
  2727.           time_stamp:=sec;
  2728.           if (time_stamp <> old_time_stamp) then
  2729.             begin
  2730.               old_time_stamp:=time_stamp;
  2731.               inc(count);
  2732.             end;
  2733.           reading:=get_s_reading;
  2734.           lineto(X_INIT + count, scale_y(reading));
  2735.           if count > max_count then
  2736.             begin
  2737.               count:=0;
  2738.               moveto(X_INIT,scale_y(reading));
  2739.             end;
  2740.         end;
  2741.       main_prompt;
  2742.       ch:=fetch; { get key pressed and discard }
  2743.     end;
  2744.  
  2745.     procedure spectral_plot;
  2746.     const BUFFERSIZE = 100;
  2747.           PLOTBUFSIZE = 1024;
  2748.     var ok,nullval:boolean;
  2749.         start,stop:integer;
  2750.         delta:real;
  2751.         last_freq, freq:real;
  2752.         freq_range:real;
  2753.         count_delta,count:integer;
  2754.         i:integer;
  2755.         s:string;
  2756.         freq_buffer: array[1..BUFFERSIZE] of byte;
  2757.         plot_buffer, plot_cnt: array[0..PLOTBUFSIZE] of byte;
  2758.         old_stat:receivertype;
  2759.         ch:char;
  2760.  
  2761.       procedure draw_x_axis;
  2762.       const POINTS = 8;
  2763.       var i,x:integer;
  2764.           del:real;
  2765.           s:string;
  2766.           f:real;
  2767.       begin
  2768.         moveto(X_AXIS,scale_y(240));
  2769.         lineto(max_x, scale_y(240));
  2770.         del:=max_count / POINTS;
  2771.         for i:=0 to POINTS do
  2772.           begin
  2773.             x:=round(X_AXIS + del * i);
  2774.             moveto(x, scale_y(242));
  2775.             lineto(x, scale_y(238));
  2776.             moveto(x - 26, scale_y(250));
  2777.             f:=start_freq + i * ((stop_freq - start_freq) / POINTS);
  2778.             str(f:7:1,s);
  2779.             outtext(s);
  2780.           end;
  2781.       end;
  2782.  
  2783.       procedure radio_setup;
  2784.       var s:string;
  2785.       begin
  2786.         old_stat:=receiverstat;
  2787.         write_com(COM_NRD,'H1'); { lock radio; cmd mode }
  2788.         set_mode(CW);
  2789.         set_bandwidth(INTER);
  2790.         write_com(COM_NRD,'W0500'); { set bw to 500hz }
  2791.         if freq_range <= 100.0 then s:='1' else s:='2';
  2792.         write_com(COM_NRD,'V' + s); { control tuning increment }
  2793.         set_agc(FAST);
  2794.         set_freq(start_freq);
  2795.         delay(200);
  2796.         write_com(COM_NRD,'H0');
  2797.       end;
  2798.  
  2799.       procedure get_scan_range;
  2800.       begin
  2801.         start:=round(start_freq);
  2802.         str(start_freq:5:0,s);
  2803.         s:='starting frequency [default=' + s + ']';
  2804.         entnum(1,5,start,ok,nullval,s);
  2805.         if not ok then exit;
  2806.         if not nullval then start_freq:=start;
  2807.         stop:=round(stop_freq);
  2808.         str(stop_freq:5:0,s);
  2809.         s:='stopping frequency [default=' + s + ']';
  2810.         entnum(1,7,stop,ok,nullval,s);
  2811.         if not ok then exit;
  2812.         if not nullval then stop_freq:=stop;
  2813.       end;
  2814.  
  2815.       procedure restore_radio; { to settings prior to spectral plot }
  2816.       begin
  2817.         remote_on;
  2818.         write_com(COM_NRD,'W2400'); { set bw to 2400hz }
  2819.         with receiverstat do
  2820.           set_all(199,attenuator,bandwidth,mode,frequency,agc);
  2821.         write_com(COM_NRD,'V0');
  2822.         write_com(COM_NRD,'H0'); { unlock radio }
  2823.         delay(REMOTE_DLY);
  2824.       end;
  2825.  
  2826.       procedure plot_point(freq:real;y:byte);
  2827.       var x,ave:integer;
  2828.           color:integer;
  2829.       begin
  2830.         { adaptively Kalman filter reading to get statistical average }
  2831.         {   the idea is to end up with a running average where the last }
  2832.         {   point has no more influence than the first  }
  2833.         x:=round(max_count * ((freq - start_freq) / freq_range));
  2834.         ave:=round((plot_cnt[x] * plot_buffer[x] + y) / (plot_cnt[x] + 1));
  2835.         plot_buffer[x]:=ave;
  2836.         if plot_cnt[x] < 255 then inc(plot_cnt[x]);
  2837.  
  2838.         { now draw point }
  2839.         if y < 99 then color:=12 else color:=11;
  2840.         putpixel(x + X_AXIS,scale_y(y),color);
  2841.       end;
  2842.  
  2843.       procedure draw_average;
  2844.       var x:integer;
  2845.       begin
  2846.         moveto(X_AXIS,scale_y(plot_buffer[0]));
  2847.         setcolor(14);
  2848.         for x:=1 to max_count do if plot_buffer[x] > 0 then
  2849.           lineto(x + X_AXIS,scale_y(plot_buffer[x]));
  2850.       end;
  2851.  
  2852.       procedure init_spectral_plot;
  2853.       begin
  2854.         init_graph;
  2855.         out_prompt('COMMANDS: A(verage, C(lear, Q(uit');
  2856.         plot_title('S P E C T R A L  P L O T');
  2857.         draw_x_axis;
  2858.       end;
  2859.  
  2860.     begin
  2861.       restorecrtmode;
  2862.       home;
  2863.       writea(LIGHTGREEN,FOREGROUND);
  2864.       writeln(output, ' SPECTRAL PLOT: Enter the frequency range to scan');
  2865.       get_scan_range;
  2866.       init_spectral_plot;
  2867.       freq_range:=stop_freq - start_freq;
  2868.       radio_setup;
  2869.  
  2870.       { init plot statistics used to Kalman filter averages }
  2871.       for i:=0 to max_count do
  2872.         begin
  2873.           plot_buffer[i]:=0;
  2874.           plot_cnt[i]:=0;
  2875.         end;
  2876.  
  2877.       last_freq:=start_freq;
  2878.       ch:=' ';
  2879.       repeat
  2880.         remote_on;
  2881.         delay(200);
  2882.         count:=0;
  2883.         write_com(COM_NRD,'Y+');
  2884.  
  2885.         { gather data }
  2886.         while not keypressed and (count < BUFFERSIZE) do
  2887.           begin
  2888.             inc(count);
  2889.             freq_buffer[count]:=get_s_reading;
  2890.           end;
  2891.         write_com(COM_NRD,'H0'); { remote_off }
  2892.         toggle_remote;
  2893.         delay(300);
  2894.         if async_buffer_check(ch) then check_status(s); { get frequency }
  2895.         freq:=receiverstat.frequency;
  2896.         if freq > stop_freq then
  2897.           begin
  2898.             remote_on;
  2899.             set_freq(start_freq);
  2900.             delay(200);
  2901.           end;
  2902.         write_com(COM_NRD,'H0');
  2903.         delta:=(freq - last_freq) / BUFFERSIZE;
  2904.  
  2905.         { plot buffer contents }
  2906.         count:=0;
  2907.         freq:=last_freq;
  2908.         while (freq < stop_freq) and (count < BUFFERSIZE) do
  2909.           begin
  2910.             inc(count);
  2911.             plot_point(freq, freq_buffer[count]);
  2912.             freq:=freq + delta;
  2913.           end;
  2914.         last_freq:=receiverstat.frequency;
  2915.         if last_freq > stop_freq then last_freq:=start_freq;
  2916.         if keypressed then
  2917.           begin
  2918.              ch:=upcase(fetch);
  2919.              case ch of
  2920.                'A': draw_average;
  2921.                'C': init_spectral_plot;
  2922.              end;
  2923.           end;
  2924.       until ch = 'Q';
  2925.       receiverstat:=old_stat;
  2926.       restore_radio;
  2927.       main_prompt;
  2928.     end;
  2929.  
  2930.   begin
  2931.     start_freq:=receiverstat.frequency - 5.0;
  2932.     stop_freq :=receiverstat.frequency + 5.0;
  2933.     if radio_type <> 535 then exit;
  2934.     max_x:=getmaxx - 30; max_y:=getmaxy;
  2935.     max_count:=max_x - X_AXIS;
  2936.     last_plot:=NONE;
  2937.     init_graph;
  2938.     main_prompt;
  2939.     repeat
  2940.       if keypressed then ch:=upcase(fetch) else ch:='@' { nop };
  2941.       case ch of
  2942.         '@':; { nop }
  2943.         'C':begin
  2944.               init_graph;
  2945.               main_prompt;
  2946.             end;
  2947.         'T':time_plot;
  2948.         'S':spectral_plot;
  2949.       end;
  2950.     until ch = 'Q';
  2951.     restorecrtmode;
  2952.     init_crt;
  2953.     write_com(COM_NRD,'H0'); { unlock radio }
  2954.     comreadln(COM_NRD,s);
  2955.     write_com(COM_NRD,'I1');
  2956.     gotoxy(x_pos,y_pos);
  2957.     show_log(rec,TRUE,TRUE);
  2958.   end;
  2959.  
  2960. begin { nrd }
  2961.   graph_init;
  2962.   old_time_stamp:=0;
  2963.   last_log:=0;
  2964.   enable_s_meter:=FALSE;
  2965.   init_com;
  2966.   if has_map then
  2967.     begin
  2968.       remote_on;  { get receiver status to see if map is on }
  2969.       remote_off(0);
  2970.       map:=receiverstat.mode = AM;  { assume MAP in use if radio in AM }
  2971.     end
  2972.   else map:=FALSE;
  2973.   prompt_num:=PAGE1;
  2974.   get_loglist(loglist);
  2975.   new_log(loglist.currentlog,rslt);
  2976.   init_crt;
  2977.   x_pos:=1; y_pos:=1;
  2978.   do_unmark(TRUE);
  2979.  
  2980.   { init old receiver status to current radio settings }
  2981.   oldstat:=receiverstat;
  2982.   if radio_type = 535 then
  2983.     begin
  2984.       toggle_remote; { get radio status; dial changes will be cont sent }
  2985.       show_receiver;
  2986.     end;
  2987.   repeat
  2988.     if (radio_type = 535) and async_buffer_check(ch) then
  2989.       begin
  2990.         check_status(s); { they changed dial }
  2991.         show_receiver;
  2992.       end;
  2993.     if enable_s_meter then timed_s_meter;
  2994.     if update_receiver_display then
  2995.       begin
  2996.         if radio_type = 525 then
  2997.           begin
  2998.             remote_on;
  2999.             show_receiver;
  3000.             remote_off(REMOTE_DLY);
  3001.           end
  3002.         else
  3003.           begin
  3004.             toggle_remote;
  3005.             show_receiver;
  3006.           end;
  3007.         update_receiver_display:=FALSE;
  3008.       end;
  3009.     if keypressed then ch:=upcase(fetch) else ch:='@' { nop };
  3010.     case ch of
  3011.       '@':; { nop }
  3012.       '+':              inc_freq;
  3013.       '-':              dec_freq;
  3014.       '*':              find_freq;
  3015.       '/':              begin
  3016.                           if prompt_num = PAGE1 then prompt_num:=PAGE2
  3017.                                                 else prompt_num:=PAGE1;
  3018.                           cmd_prompt(prompt_num);
  3019.                           bottom_window;
  3020.                         end;
  3021.       'A':              begin
  3022.                           close(logbuf);
  3023.                           do_alternate;
  3024.                         end;
  3025.       'C':              do_confirm;
  3026.       'P':              do_page;
  3027.       'S':              do_sort(FALSE);
  3028.       'E':              do_edit;
  3029.       'G':              do_graph;
  3030.       'J':              do_journal;
  3031.       'D':              do_delete;
  3032.       'N':              do_undelete;
  3033.       'M':              do_mark;
  3034.       'U':              do_unmark(TRUE);
  3035.       'L':              do_log;
  3036.       'R':              begin
  3037.                           enable_s_meter:=not enable_s_meter;
  3038.                           if not enable_s_meter then
  3039.                             begin
  3040.                               top_window;
  3041.                               gotoxy(42,3);
  3042.                               write(output,'          ');
  3043.                               bottom_window;
  3044.                             end;
  3045.                         end;
  3046.       'T':              do_tune;
  3047.       'K':              if has_map then do_kiwa;
  3048.       'W':              do_write;
  3049.       '>':              inc_mode;
  3050.       '.':              inc_mode;
  3051.       '<':              dec_mode;
  3052.       ',':              dec_mode;
  3053.       ']':              inc_bandwidth;
  3054.       '[':              dec_bandwidth;
  3055.       'H':              begin
  3056.                           call_do_help;
  3057.                           status_window;
  3058.                         end;
  3059.       PAGEUP:           do_pageup(1);
  3060.       PAGEDOWN:         do_pagedown(1);
  3061.       UP:               do_up;
  3062.       DOWN:             do_down;
  3063.       RIGHTARROW:       do_right;
  3064.       LEFTARROW:        do_left;
  3065.       BACKTAB:          do_backtab;
  3066.       TAB:              do_tab;
  3067.       CTRLPAGEUP:       do_pageup(10);
  3068.       CTRLPAGEDN:       do_pagedown(10);
  3069.       HOMEKY:           do_home;
  3070.       ENDKY:            do_end;
  3071.       else update_receiver_display:=TRUE;
  3072.     end;
  3073.   until ch = 'Q';
  3074.   if radio_type = 535 then write_com(COM_NRD,'I0'); { unlock radio }
  3075.   sync_loglist;
  3076.   close(logbuf);
  3077.   window(1,1,80,25);
  3078.   home;
  3079.   gotoxy(1,8);
  3080.   writeln(output,'Send comments and suggestions to:');
  3081.   writeln(output);
  3082.   writeln(output,'    Tom Whiteside (512) 258-5924');
  3083.   writeln(output,'    11505 Oak View');
  3084.   writeln(output,'    Austin, TX 78759');
  3085. end.  { nrd }
  3086.